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
3 Answers
Reset to default 2Or 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);
}