谷歌地图V3:使用自定义标记进行聚类

10
我正在尝试使用MarkerClusterer对地图上的标记进行聚类。问题是,我没有使用默认标记(google.maps.Marker),而是使用一个继承自google.maps.OverlayView的自定义类。 不幸的是,似乎该库是在假定使用基本标记的情况下开发的,事实上,我会因为我的类未实现google.maps.Marker中定义的方法而出现错误。 是否可能通过保留我的自定义标记来使用MarkerClusterer编辑:比我预期的要简单得多,我通过在我的自定义类中实现了2个方法来解决这个问题: setVisible()getPosition() 为了帮助其他人,以下是我的完整接口(没有完整实现):
BFPushpin = function(config) 
{
    this.setMap(config.map);
    this.set("position", config.position);
    // other settings...
};

// my class extends google.maps.OverlayView
BFPushpin.prototype = new google.maps.OverlayView();

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

BFPushpin.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);
};

BFPushpin.prototype.getSuperContainer = function()
{
    var panes = this.getPanes();
    return jQuery(panes ? panes.overlayImage : "");
};

BFPushpin.prototype.getContainer = function()
{
    // return inner container
};

BFPushpin.prototype._generatePopupContent = function()
{
    // return markup for the popupwindow
};

BFPushpin.prototype._addListeners = function()
{
    // add handlers for the pushpin
};

BFPushpin.prototype.onAdd = function()
{
    // customize content here
};

BFPushpin.prototype.onRemove = function()
{
    // remove pin container here
};

BFPushpin.prototype.draw = function()
{
    // set display style here
};

BFPushpin.prototype.setVisible = function(visible)
{
    // set display block or hidden
};

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

1
我对你的解决方案有点困惑。我正在尝试做类似的事情,我有一个自定义覆盖层,它“继承”自OverlayView,并且我通过在draw函数中简单地枚举我的自己制作的对象列表来将标记绘制为标记。那么你是如何调和这里使用“Marker”,以使聚类功能正常工作的呢? - Brandon
你是为每个标记渲染一个完整的叠加层吗? - Brandon
3个回答

2

或者只需定义MarkerClusterer在标记上期望的函数。setMap和getPosition()以及其他一些函数。


这是危险的,因为你永远不知道未来版本/其他库和方法等将使用哪些方法。 - Tomas
并不是,因为您只需要实现标记接口,该接口在API中非常稳定,所以您不应该遇到任何问题。MarkerClusterer只关心获取项目的位置并能够设置其可见性/地图。 - skarE

1

你应该定义你的新标记类,使其也继承自google.maps.Marker(即实现它的接口)。MarkerClusterer使用这个接口是很合理的 - 它必须假设这些标记是标记,以便与它们一起工作 :-)


1

希望这也能帮助那些试图让这个解决方案工作的人。感谢@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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接