Javascript GoogleMapsV3:使用自定义标记进行聚类

Javascript GoogleMapsV3:使用自定义标记进行聚类,javascript,google-maps,google-maps-api-3,Javascript,Google Maps,Google Maps Api 3,我想用它把地图上的标记组合起来。 问题是我没有使用默认标记(google.maps.Marker),而是使用了一个自定义类,它从google.maps.overlyview中删除。 不幸的是,这个库似乎是在假设使用基本标记的情况下开发的,事实上,我会出错,因为我的类没有实现在google.maps.Marker中定义的方法。 是否可以通过保留我的自定义标记来使用标记聚类器 编辑:这比我预期的要简单得多,我通过在自定义类中实现两个方法解决了这个问题: setVisible()和getPositio

我想用它把地图上的标记组合起来。 问题是我没有使用默认标记(google.maps.Marker),而是使用了一个自定义类,它从google.maps.overlyview中删除。 不幸的是,这个库似乎是在假设使用基本标记的情况下开发的,事实上,我会出错,因为我的类没有实现在google.maps.Marker中定义的方法。 是否可以通过保留我的自定义标记来使用标记聚类器

编辑:这比我预期的要简单得多,我通过在自定义类中实现两个方法解决了这个问题:

setVisible()getPosition()

为了帮助他人,以下是我的完整界面(未完全实现):


您可能应该以这样一种方式定义新的marker类:它也继承自
google.maps.marker
(即,它实现其接口)。MarkerClusterer使用此接口是合乎逻辑的-必须假设标记是标记才能使用它们:-)

或者只定义MarkerClusterer在标记上期望的功能。setMap和getPosition()以及其他一些解决方案。

希望这也能帮助尝试使用此解决方案的人。感谢@daveoncode提供的示例。我能够对其进行修改,使其为我工作:

renderMap() {
    const mapProperties = {
        center: new google.maps.LatLng(34.0234, -84.6155),
        zoom: 10,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    this.map = new google.maps.Map(this.mapElement.nativeElement, mapProperties);

    let markers = [];
    for (let i=0; i<this._sitesList.length; i++) {
        let bounds = new google.maps.LatLngBounds(
            new google.maps.LatLng(this._sitesList[i].lat, this._sitesList[i].lon)
        );
        let position = new google.maps.LatLng(this._sitesList[i].lat, this._sitesList[i].lon);
        let html = this.makeHtmlForSitePanel(i, this._sitesList[i]); // I have a function to return html for my OverlayView panels here.
        markers.push( this.generateSitePanel(bounds, html, this.map, position) );
    }

    var markerCluster = new MarkerClusterer(this.map, markers, {
        imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'
    });

}

generateSitePanel(bounds, html, map, position) {

    SitePanel.prototype = new google.maps.OverlayView();

    function SitePanel (bounds, html, map, position) {
        this.bounds_ = bounds;
        this.set('position', position);
        this.html_ = html;
        this.map_ = map;
        this.div_ = null;
        this.setMap(map);
    }

    SitePanel.prototype.getBounds = function() {
        return new google.maps.LatLngBounds(this.position, this.position); 
    };

    SitePanel.prototype.getPoint = function() {
        var bounds = this.getBounds();
        var projection = this.getProjection();
        var sw = projection.fromLatLngToDivPixel(bounds.getSouthWest());  
            var ne = projection.fromLatLngToDivPixel(bounds.getNorthEast()); 

        return new google.maps.Point(sw.x, ne.y);
    };

    SitePanel.prototype.getSuperContainer = function(){
        var panes = this.getPanes();
        return $(panes ? panes.overlayImage : '');
    };

    SitePanel.prototype.getContainer = function()
    {
        // return inner container
        // I don't have anything for this one
    };

    SitePanel.prototype.getPosition = function() {
        return this.position;
    };

    SitePanel.prototype.onAdd = function() {
        var div = document.createElement('div');
        div.className = 'tooltip-container-';
        div.innerHTML = this.html_;
        div.style.position = 'absolute';
        this.div_ = div;
        var panes = this.getPanes();
        panes.overlayImage.appendChild(div);
    };

    SitePanel.prototype.draw = function() {
        var overlayProjection = this.getProjection();
        var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
        var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

        var div = this.div_;
        div.style.left = sw.x + 'px';
        div.style.top = ne.y + 20 + 'px';
    };

    SitePanel.prototype.onRemove = function() {
        this.div_.parentNode.removeChild(this.div_);
        this.div_ = null;
    };

    return new SitePanel(bounds, html, map, position);
}
renderMap(){
常量映射属性={
中心:新google.maps.LatLng(34.0234,-84.6155),
缩放:10,
mapTypeId:google.maps.mapTypeId.ROADMAP
};
this.map=new google.maps.map(this.mapeElement.nativeElement,mapProperties);
让标记=[];

对于(设i=0;这很危险,因为你永远不知道未来版本/其他库和方法等可以使用哪些方法。不知道,因为你只是在实现API中非常可用的标记接口,你不应该有问题。MarkerClusterer只关心获取项的位置并能够设置它的可见性/映射。我对你的解决方案有点困惑。我正在尝试做类似的事情,我有一个自定义覆盖,它“继承”自OverlayView,我通过在draw函数中枚举我自己制作的对象列表,将标记作为标记绘制在上面。那么你如何协调“标记”的使用在这里,集群功能正常?是否为每个标记呈现一个完整的覆盖?
renderMap() {
    const mapProperties = {
        center: new google.maps.LatLng(34.0234, -84.6155),
        zoom: 10,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    this.map = new google.maps.Map(this.mapElement.nativeElement, mapProperties);

    let markers = [];
    for (let i=0; i<this._sitesList.length; i++) {
        let bounds = new google.maps.LatLngBounds(
            new google.maps.LatLng(this._sitesList[i].lat, this._sitesList[i].lon)
        );
        let position = new google.maps.LatLng(this._sitesList[i].lat, this._sitesList[i].lon);
        let html = this.makeHtmlForSitePanel(i, this._sitesList[i]); // I have a function to return html for my OverlayView panels here.
        markers.push( this.generateSitePanel(bounds, html, this.map, position) );
    }

    var markerCluster = new MarkerClusterer(this.map, markers, {
        imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'
    });

}

generateSitePanel(bounds, html, map, position) {

    SitePanel.prototype = new google.maps.OverlayView();

    function SitePanel (bounds, html, map, position) {
        this.bounds_ = bounds;
        this.set('position', position);
        this.html_ = html;
        this.map_ = map;
        this.div_ = null;
        this.setMap(map);
    }

    SitePanel.prototype.getBounds = function() {
        return new google.maps.LatLngBounds(this.position, this.position); 
    };

    SitePanel.prototype.getPoint = function() {
        var bounds = this.getBounds();
        var projection = this.getProjection();
        var sw = projection.fromLatLngToDivPixel(bounds.getSouthWest());  
            var ne = projection.fromLatLngToDivPixel(bounds.getNorthEast()); 

        return new google.maps.Point(sw.x, ne.y);
    };

    SitePanel.prototype.getSuperContainer = function(){
        var panes = this.getPanes();
        return $(panes ? panes.overlayImage : '');
    };

    SitePanel.prototype.getContainer = function()
    {
        // return inner container
        // I don't have anything for this one
    };

    SitePanel.prototype.getPosition = function() {
        return this.position;
    };

    SitePanel.prototype.onAdd = function() {
        var div = document.createElement('div');
        div.className = 'tooltip-container-';
        div.innerHTML = this.html_;
        div.style.position = 'absolute';
        this.div_ = div;
        var panes = this.getPanes();
        panes.overlayImage.appendChild(div);
    };

    SitePanel.prototype.draw = function() {
        var overlayProjection = this.getProjection();
        var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
        var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

        var div = this.div_;
        div.style.left = sw.x + 'px';
        div.style.top = ne.y + 20 + 'px';
    };

    SitePanel.prototype.onRemove = function() {
        this.div_.parentNode.removeChild(this.div_);
        this.div_ = null;
    };

    return new SitePanel(bounds, html, map, position);
}