最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Google maps v3: clustering with custom markers - Stack Overflow

programmeradmin1浏览0评论

I'm trying to use MarkerClusterer to clusterize the markers on my map. The problem is that I'm not using default markers (google.maps.Marker), but instead a custom class which hinerits from google.maps.OverlayView. Unfortunately it seems that the library has been developed assuming the use of basic markers, in fact I get errors because my class does not implement methods defined in google.maps.Marker. Is it possible to use the MarkerClusterer by keeping my custom markers?

EDIT: it was a lot easier than I expected, I solved by implementing 2 methods in my custom class:

setVisible() and getPosition()

in order to help others the following is my plete interface (without full implementation):

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;
};

I'm trying to use MarkerClusterer to clusterize the markers on my map. The problem is that I'm not using default markers (google.maps.Marker), but instead a custom class which hinerits from google.maps.OverlayView. Unfortunately it seems that the library has been developed assuming the use of basic markers, in fact I get errors because my class does not implement methods defined in google.maps.Marker. Is it possible to use the MarkerClusterer by keeping my custom markers?

EDIT: it was a lot easier than I expected, I solved by implementing 2 methods in my custom class:

setVisible() and getPosition()

in order to help others the following is my plete interface (without full implementation):

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;
};
Share Improve this question edited Nov 29, 2011 at 11:58 daveoncode asked Nov 28, 2011 at 14:40 daveoncodedaveoncode 19.6k19 gold badges108 silver badges162 bronze badges 2
  • 1 Im a little confused by your solution. I am trying to do something similar, I have a custom overlay that "inherits" from OverlayView and I am drawing the markers on there as markup by simply enumerating a list of my objects of my own making in the draw function. So how are you reconciling the use of "Marker" here such that the clustering is functioning? – Brandon Commented Apr 8, 2015 at 18:29
  • Are you rendering one plete overlay for each marker? – Brandon Commented Apr 8, 2015 at 18:58
Add a ment  | 

3 Answers 3

Reset to default 2

Or just define the functions that the MarkerClusterer expects on the marker. setMap and getPosition() and some other ones.

You should probably define your new marker class in such a way that it also inherits from google.maps.Marker (i.e. that it implements its interface). It is logical that MarkerClusterer uses this interface - it has to suppose the markers are markers in order to work with them :-)

Hopefully this will also help people trying to get this solution to work. Thanks @daveoncode for the example. I was able to modify it to get it working for me:

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./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);
}
发布评论

评论列表(0)

  1. 暂无评论