Socket
Socket
Sign inDemoInstall

@react-google-maps/marker-clusterer

Package Overview
Dependencies
Maintainers
2
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@react-google-maps/marker-clusterer - npm Package Compare versions

Comparing version 2.3.0 to 2.3.1

49

dist/index.d.ts

@@ -1,3 +0,1 @@

/// <reference types="googlemaps" />
/* globals google */
interface ClusterIconInfo {

@@ -8,6 +6,6 @@ text: string;

}
type MarkerExtended = google.maps.Marker & {
declare type MarkerExtended = google.maps.Marker & {
isAdded?: boolean;
};
type TCalculator = (markers: MarkerExtended[], num: number) => ClusterIconInfo;
declare type TCalculator = (markers: MarkerExtended[], num: number) => ClusterIconInfo;
interface ClustererOptions {

@@ -46,2 +44,3 @@ gridSize?: number;

}
declare class ClusterIcon {

@@ -79,2 +78,3 @@ cluster: Cluster;

}
declare class Cluster {

@@ -104,2 +104,3 @@ markerClusterer: Clusterer;

}
declare class Clusterer {

@@ -130,5 +131,3 @@ markers: MarkerExtended[];

onAdd(): void;
// eslint-disable-next-line @getify/proper-arrows/this
onRemove(): void;
// eslint-disable-next-line @typescript-eslint/no-empty-function
draw(): void;

@@ -188,37 +187,3 @@ setupStyles(): void;

}
/**
* @name MarkerClusterer for Google Maps V3
* @version 1.0.0 [March 2019]
* @author Alexey Lyakhov
* @fileoverview
* The library creates and manages per-zoom-level clusters for large amounts of markers.
* <p>
* This is an enhanced V3 implementation of the
* <a href="http://gmaps-utility-library-dev.googlecode.com/svn/tags/markerclusterer/"
* >V2 MarkerClusterer</a> by Xiaoxi Wu. It is based on the
* <a href="http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerclusterer/"
* >V3 MarkerClusterer</a> port by Luke Mahe. MarkerClustererPlus was created by Gary Little.
* <p>
* v2.0 release: MarkerClustererPlus v2.0 is backward compatible with MarkerClusterer v1.0. It
* adds support for the <code>ignoreHidden</code>, <code>title</code>, <code>batchSizeIE</code>,
* and <code>calculator</code> properties as well as support for four more events. It also allows
* greater control over the styling of the text that appears on the cluster marker. The
* documentation has been significantly improved and the overall code has been simplified and
* polished. Very large numbers of markers can now be managed without causing Javascript timeout
* errors on Internet Explorer. Note that the name of the <code>clusterclick</code> event has been
* deprecated. The new name is <code>click</code>, so please change your application code now.
*/
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { Clusterer, Cluster, ClusterIcon, ClusterIconInfo, ClusterIconStyle, MarkerExtended, TCalculator, ClustererOptions };
export { Cluster, ClusterIcon, ClusterIconInfo, ClusterIconStyle, Clusterer, ClustererOptions, MarkerExtended, TCalculator };

1876

dist/umd.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.markerClusterer = {}));
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.markerClusterer = {}));
}(this, (function (exports) { 'use strict';
var ClusterIcon = /** @class */ (function () {
function ClusterIcon(cluster, styles) {
cluster.getClusterer().extend(ClusterIcon, google.maps.OverlayView);
this.cluster = cluster;
this.className = this.cluster.getClusterer().getClusterClass();
this.styles = styles;
this.center = undefined;
this.div = null;
this.sums = null;
this.visible = false;
this.boundsChangedListener = null;
this.url = '';
this.height = 0;
this.width = 0;
this.anchorText = [0, 0];
this.anchorIcon = [0, 0];
this.textColor = 'black';
this.textSize = 11;
this.textDecoration = 'none';
this.fontWeight = 'bold';
this.fontStyle = 'normal';
this.fontFamily = 'Arial,sans-serif';
this.backgroundPosition = '0 0';
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.setMap(cluster.getMap()); // Note: this causes onAdd to be called
}
ClusterIcon.prototype.onAdd = function () {
var _this = this;
var cMouseDownInCluster;
var cDraggingMapByCluster;
this.div = document.createElement('div');
this.div.className = this.className;
if (this.visible) {
this.show();
}
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getPanes().overlayMouseTarget.appendChild(this.div);
// Fix for Issue 157
this.boundsChangedListener = google.maps.event.addListener(
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap(), 'boundschanged', function boundsChanged() {
cDraggingMapByCluster = cMouseDownInCluster;
});
google.maps.event.addDomListener(this.div, 'mousedown', function onMouseDown() {
cMouseDownInCluster = true;
cDraggingMapByCluster = false;
});
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
google.maps.event.addDomListener(this.div, 'click',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function (event) {
cMouseDownInCluster = false;
if (!cDraggingMapByCluster) {
var markerClusterer_1 = _this.cluster.getClusterer();
/**
* This event is fired when a cluster marker is clicked.
* @name MarkerClusterer#click
* @param {Cluster} c The cluster that was clicked.
* @event
*/
google.maps.event.trigger(markerClusterer_1, 'click', _this.cluster);
google.maps.event.trigger(markerClusterer_1, 'clusterclick', _this.cluster); // deprecated name
// The default click handler follows. Disable it by setting
// the zoomOnClick property to false.
if (markerClusterer_1.getZoomOnClick()) {
// Zoom into the cluster.
var maxZoom_1 = markerClusterer_1.getMaxZoom();
var bounds_1 = _this.cluster.getBounds();
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
markerClusterer_1.getMap().fitBounds(bounds_1);
// There is a fix for Issue 170 here:
setTimeout(function timeout() {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
markerClusterer_1.getMap().fitBounds(bounds_1);
// Don't zoom beyond the max zoom level
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
if (maxZoom_1 !== null && markerClusterer_1.getMap().getZoom() > maxZoom_1) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
markerClusterer_1.getMap().setZoom(maxZoom_1 + 1);
}
}, 100);
}
// Prevent event propagation to the map:
event.cancelBubble = true;
if (event.stopPropagation) {
event.stopPropagation();
}
}
});
google.maps.event.addDomListener(this.div, 'mouseover',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
/**
* This event is fired when the mouse moves over a cluster marker.
* @name MarkerClusterer#mouseover
* @param {Cluster} c The cluster that the mouse moved over.
* @event
*/
google.maps.event.trigger(_this.cluster.getClusterer(), 'mouseover', _this.cluster);
});
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
google.maps.event.addDomListener(this.div, 'mouseout',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
/**
* This event is fired when the mouse moves out of a cluster marker.
* @name MarkerClusterer#mouseout
* @param {Cluster} c The cluster that the mouse moved out of.
* @event
*/
google.maps.event.trigger(_this.cluster.getClusterer(), 'mouseout', _this.cluster);
});
};
ClusterIcon.prototype.onRemove = function () {
if (this.div && this.div.parentNode) {
this.hide();
if (this.boundsChangedListener !== null) {
google.maps.event.removeListener(this.boundsChangedListener);
}
google.maps.event.clearInstanceListeners(this.div);
this.div.parentNode.removeChild(this.div);
this.div = null;
}
};
ClusterIcon.prototype.draw = function () {
if (this.visible && this.div !== null && this.center) {
var _a = this.getPosFromLatLng(this.center), x = _a.x, y = _a.y;
this.div.style.top = y + 'px';
this.div.style.left = x + 'px';
}
};
ClusterIcon.prototype.hide = function () {
if (this.div) {
this.div.style.display = 'none';
}
this.visible = false;
};
ClusterIcon.prototype.show = function () {
if (this.div && this.center) {
var img = '', divTitle = '';
// NOTE: values must be specified in px units
var bp = this.backgroundPosition.split(' ');
var spriteH = parseInt(bp[0].replace(/^\s+|\s+$/g, ''), 10);
var spriteV = parseInt(bp[1].replace(/^\s+|\s+$/g, ''), 10);
var pos = this.getPosFromLatLng(this.center);
if (this.sums === null || typeof this.sums.title === 'undefined' || this.sums.title === '') {
divTitle = this.cluster.getClusterer().getTitle();
}
else {
divTitle = this.sums.title;
}
this.div.style.cssText = this.createCss(pos);
img =
"<img alt='" +
divTitle +
"' src='" +
this.url +
"' style='position: absolute; top: " +
spriteV +
'px; left: ' +
spriteH +
'px; ';
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
if (!this.cluster.getClusterer().enableRetinaIcons) {
img +=
'clip: rect(' +
-1 * spriteV +
'px, ' +
(-1 * spriteH + this.width) +
'px, ' +
(-1 * spriteV + this.height) +
'px, ' +
-1 * spriteH +
'px);';
}
img += "'>";
this.div.innerHTML =
img +
"<div style='" +
'position: absolute;' +
'top: ' +
this.anchorText[0] +
'px;' +
'left: ' +
this.anchorText[1] +
'px;' +
'color: ' +
this.textColor +
';' +
'font-size: ' +
this.textSize +
'px;' +
'font-family: ' +
this.fontFamily +
';' +
'font-weight: ' +
this.fontWeight +
';' +
'font-style: ' +
this.fontStyle +
';' +
'text-decoration: ' +
this.textDecoration +
';' +
'text-align: center;' +
'width: ' +
this.width +
'px;' +
'line-height:' +
this.height +
'px;' +
"'>" +
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.sums.text +
'</div>';
this.div.title = divTitle;
this.div.style.display = '';
}
this.visible = true;
};
ClusterIcon.prototype.useStyle = function (sums) {
this.sums = sums;
var style = this.styles[Math.min(this.styles.length - 1, Math.max(0, sums.index - 1))];
this.url = style.url;
this.height = style.height;
this.width = style.width;
if (style.className)
this.className = this.className + " " + style.className;
this.anchorText = style.anchorText || [0, 0];
this.anchorIcon = style.anchorIcon || [this.height / 2, this.width / 2];
this.textColor = style.textColor || 'black';
this.textSize = style.textSize || 11;
this.textDecoration = style.textDecoration || 'none';
this.fontWeight = style.fontWeight || 'bold';
this.fontStyle = style.fontStyle || 'normal';
this.fontFamily = style.fontFamily || 'Arial,sans-serif';
this.backgroundPosition = style.backgroundPosition || '0 0';
};
ClusterIcon.prototype.setCenter = function (center) {
this.center = center;
};
ClusterIcon.prototype.createCss = function (pos) {
var style = [];
style.push('cursor: pointer;');
style.push('position: absolute; top: ' + pos.y + 'px; left: ' + pos.x + 'px;');
style.push('width: ' + this.width + 'px; height: ' + this.height + 'px;');
return style.join('');
};
ClusterIcon.prototype.getPosFromLatLng = function (latlng) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
var pos = this.getProjection().fromLatLngToDivPixel(latlng);
pos.x -= this.anchorIcon[1];
pos.y -= this.anchorIcon[0];
// pos.x = pos.x
// pos.y = pos.y
return pos;
};
return ClusterIcon;
}());
var ClusterIcon = /** @class */ (function () {
function ClusterIcon(cluster, styles) {
cluster.getClusterer().extend(ClusterIcon, google.maps.OverlayView);
this.cluster = cluster;
this.className = this.cluster.getClusterer().getClusterClass();
this.styles = styles;
this.center = undefined;
this.div = null;
this.sums = null;
this.visible = false;
this.boundsChangedListener = null;
this.url = '';
this.height = 0;
this.width = 0;
this.anchorText = [0, 0];
this.anchorIcon = [0, 0];
this.textColor = 'black';
this.textSize = 11;
this.textDecoration = 'none';
this.fontWeight = 'bold';
this.fontStyle = 'normal';
this.fontFamily = 'Arial,sans-serif';
this.backgroundPosition = '0 0';
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.setMap(cluster.getMap()); // Note: this causes onAdd to be called
}
ClusterIcon.prototype.onAdd = function () {
var _this = this;
var cMouseDownInCluster;
var cDraggingMapByCluster;
this.div = document.createElement('div');
this.div.className = this.className;
if (this.visible) {
this.show();
}
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getPanes().overlayMouseTarget.appendChild(this.div);
// Fix for Issue 157
this.boundsChangedListener = google.maps.event.addListener(
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap(), 'boundschanged', function boundsChanged() {
cDraggingMapByCluster = cMouseDownInCluster;
});
google.maps.event.addDomListener(this.div, 'mousedown', function onMouseDown() {
cMouseDownInCluster = true;
cDraggingMapByCluster = false;
});
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
google.maps.event.addDomListener(this.div, 'click',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function (event) {
cMouseDownInCluster = false;
if (!cDraggingMapByCluster) {
var markerClusterer_1 = _this.cluster.getClusterer();
/**
* This event is fired when a cluster marker is clicked.
* @name MarkerClusterer#click
* @param {Cluster} c The cluster that was clicked.
* @event
*/
google.maps.event.trigger(markerClusterer_1, 'click', _this.cluster);
google.maps.event.trigger(markerClusterer_1, 'clusterclick', _this.cluster); // deprecated name
// The default click handler follows. Disable it by setting
// the zoomOnClick property to false.
if (markerClusterer_1.getZoomOnClick()) {
// Zoom into the cluster.
var maxZoom_1 = markerClusterer_1.getMaxZoom();
var bounds_1 = _this.cluster.getBounds();
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
markerClusterer_1.getMap().fitBounds(bounds_1);
// There is a fix for Issue 170 here:
setTimeout(function timeout() {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
markerClusterer_1.getMap().fitBounds(bounds_1);
// Don't zoom beyond the max zoom level
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
if (maxZoom_1 !== null && markerClusterer_1.getMap().getZoom() > maxZoom_1) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
markerClusterer_1.getMap().setZoom(maxZoom_1 + 1);
}
}, 100);
}
// Prevent event propagation to the map:
event.cancelBubble = true;
if (event.stopPropagation) {
event.stopPropagation();
}
}
});
google.maps.event.addDomListener(this.div, 'mouseover',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
/**
* This event is fired when the mouse moves over a cluster marker.
* @name MarkerClusterer#mouseover
* @param {Cluster} c The cluster that the mouse moved over.
* @event
*/
google.maps.event.trigger(_this.cluster.getClusterer(), 'mouseover', _this.cluster);
});
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
google.maps.event.addDomListener(this.div, 'mouseout',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
/**
* This event is fired when the mouse moves out of a cluster marker.
* @name MarkerClusterer#mouseout
* @param {Cluster} c The cluster that the mouse moved out of.
* @event
*/
google.maps.event.trigger(_this.cluster.getClusterer(), 'mouseout', _this.cluster);
});
};
ClusterIcon.prototype.onRemove = function () {
if (this.div && this.div.parentNode) {
this.hide();
if (this.boundsChangedListener !== null) {
google.maps.event.removeListener(this.boundsChangedListener);
}
google.maps.event.clearInstanceListeners(this.div);
this.div.parentNode.removeChild(this.div);
this.div = null;
}
};
ClusterIcon.prototype.draw = function () {
if (this.visible && this.div !== null && this.center) {
var _a = this.getPosFromLatLng(this.center), x = _a.x, y = _a.y;
this.div.style.top = y + 'px';
this.div.style.left = x + 'px';
}
};
ClusterIcon.prototype.hide = function () {
if (this.div) {
this.div.style.display = 'none';
}
this.visible = false;
};
ClusterIcon.prototype.show = function () {
if (this.div && this.center) {
var img = '', divTitle = '';
// NOTE: values must be specified in px units
var bp = this.backgroundPosition.split(' ');
var spriteH = parseInt(bp[0].replace(/^\s+|\s+$/g, ''), 10);
var spriteV = parseInt(bp[1].replace(/^\s+|\s+$/g, ''), 10);
var pos = this.getPosFromLatLng(this.center);
if (this.sums === null || typeof this.sums.title === 'undefined' || this.sums.title === '') {
divTitle = this.cluster.getClusterer().getTitle();
}
else {
divTitle = this.sums.title;
}
this.div.style.cssText = this.createCss(pos);
img =
"<img alt='" +
divTitle +
"' src='" +
this.url +
"' style='position: absolute; top: " +
spriteV +
'px; left: ' +
spriteH +
'px; ';
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
if (!this.cluster.getClusterer().enableRetinaIcons) {
img +=
'clip: rect(' +
-1 * spriteV +
'px, ' +
(-1 * spriteH + this.width) +
'px, ' +
(-1 * spriteV + this.height) +
'px, ' +
-1 * spriteH +
'px);';
}
img += "'>";
this.div.innerHTML =
img +
"<div style='" +
'position: absolute;' +
'top: ' +
this.anchorText[0] +
'px;' +
'left: ' +
this.anchorText[1] +
'px;' +
'color: ' +
this.textColor +
';' +
'font-size: ' +
this.textSize +
'px;' +
'font-family: ' +
this.fontFamily +
';' +
'font-weight: ' +
this.fontWeight +
';' +
'font-style: ' +
this.fontStyle +
';' +
'text-decoration: ' +
this.textDecoration +
';' +
'text-align: center;' +
'width: ' +
this.width +
'px;' +
'line-height:' +
this.height +
'px;' +
"'>" +
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.sums.text +
'</div>';
this.div.title = divTitle;
this.div.style.display = '';
}
this.visible = true;
};
ClusterIcon.prototype.useStyle = function (sums) {
this.sums = sums;
var style = this.styles[Math.min(this.styles.length - 1, Math.max(0, sums.index - 1))];
this.url = style.url;
this.height = style.height;
this.width = style.width;
if (style.className)
this.className = this.className + " " + style.className;
this.anchorText = style.anchorText || [0, 0];
this.anchorIcon = style.anchorIcon || [this.height / 2, this.width / 2];
this.textColor = style.textColor || 'black';
this.textSize = style.textSize || 11;
this.textDecoration = style.textDecoration || 'none';
this.fontWeight = style.fontWeight || 'bold';
this.fontStyle = style.fontStyle || 'normal';
this.fontFamily = style.fontFamily || 'Arial,sans-serif';
this.backgroundPosition = style.backgroundPosition || '0 0';
};
ClusterIcon.prototype.setCenter = function (center) {
this.center = center;
};
ClusterIcon.prototype.createCss = function (pos) {
var style = [];
style.push('cursor: pointer;');
style.push('position: absolute; top: ' + pos.y + 'px; left: ' + pos.x + 'px;');
style.push('width: ' + this.width + 'px; height: ' + this.height + 'px;');
return style.join('');
};
ClusterIcon.prototype.getPosFromLatLng = function (latlng) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
var pos = this.getProjection().fromLatLngToDivPixel(latlng);
pos.x -= this.anchorIcon[1];
pos.y -= this.anchorIcon[0];
// pos.x = pos.x
// pos.y = pos.y
return pos;
};
return ClusterIcon;
}());
var Cluster = /** @class */ (function () {
function Cluster(markerClusterer) {
this.markerClusterer = markerClusterer;
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.map = this.markerClusterer.getMap();
this.gridSize = this.markerClusterer.getGridSize();
this.minClusterSize = this.markerClusterer.getMinimumClusterSize();
this.averageCenter = this.markerClusterer.getAverageCenter();
this.markers = [];
this.center = undefined;
this.bounds = null;
this.clusterIcon = new ClusterIcon(this, this.markerClusterer.getStyles());
}
Cluster.prototype.getSize = function () {
return this.markers.length;
};
Cluster.prototype.getMarkers = function () {
return this.markers;
};
Cluster.prototype.getCenter = function () {
return this.center;
};
Cluster.prototype.getMap = function () {
return this.map;
};
Cluster.prototype.getClusterer = function () {
return this.markerClusterer;
};
Cluster.prototype.getBounds = function () {
var bounds = new google.maps.LatLngBounds(this.center, this.center);
var markers = this.getMarkers();
for (var i = 0; i < markers.length; i++) {
var position = markers[i].getPosition();
if (position) {
bounds.extend(position);
}
}
return bounds;
};
Cluster.prototype.remove = function () {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.clusterIcon.setMap(null);
this.markers = [];
// @ts-ignore
delete this.markers;
};
Cluster.prototype.addMarker = function (marker) {
if (this.isMarkerAlreadyAdded(marker)) {
return false;
}
if (!this.center) {
var position = marker.getPosition();
if (position) {
this.center = position;
this.calculateBounds();
}
}
else {
if (this.averageCenter) {
var position = marker.getPosition();
if (position) {
var length_1 = this.markers.length + 1;
this.center = new google.maps.LatLng((this.center.lat() * (length_1 - 1) + position.lat()) / length_1, (this.center.lng() * (length_1 - 1) + position.lng()) / length_1);
this.calculateBounds();
}
}
}
marker.isAdded = true;
this.markers.push(marker);
var mCount = this.markers.length;
var maxZoom = this.markerClusterer.getMaxZoom();
if (maxZoom !== null && this.map.getZoom() > maxZoom) {
// Zoomed in past max zoom, so show the marker.
if (marker.getMap() !== this.map) {
marker.setMap(this.map);
}
}
else if (mCount < this.minClusterSize) {
// Min cluster size not reached so show the marker.
if (marker.getMap() !== this.map) {
marker.setMap(this.map);
}
}
else if (mCount === this.minClusterSize) {
// Hide the markers that were showing.
for (var i = 0; i < mCount; i++) {
this.markers[i].setMap(null);
}
}
else {
marker.setMap(null);
}
return true;
};
Cluster.prototype.isMarkerInClusterBounds = function (marker) {
if (this.bounds !== null) {
var position = marker.getPosition();
if (position) {
return this.bounds.contains(position);
}
}
return false;
};
Cluster.prototype.calculateBounds = function () {
this.bounds = this.markerClusterer.getExtendedBounds(new google.maps.LatLngBounds(this.center, this.center));
};
Cluster.prototype.updateIcon = function () {
var mCount = this.markers.length;
var maxZoom = this.markerClusterer.getMaxZoom();
if (maxZoom !== null && this.map.getZoom() > maxZoom) {
this.clusterIcon.hide();
return;
}
if (mCount < this.minClusterSize) {
// Min cluster size not yet reached.
this.clusterIcon.hide();
return;
}
if (this.center) {
this.clusterIcon.setCenter(this.center);
}
this.clusterIcon.useStyle(this.markerClusterer.getCalculator()(this.markers, this.markerClusterer.getStyles().length));
this.clusterIcon.show();
};
Cluster.prototype.isMarkerAlreadyAdded = function (marker) {
if (this.markers.includes) {
return this.markers.includes(marker);
}
else {
for (var i = 0; i < this.markers.length; i++) {
if (marker === this.markers[i]) {
return true;
}
}
}
return false;
};
return Cluster;
}());
var Cluster = /** @class */ (function () {
function Cluster(markerClusterer) {
this.markerClusterer = markerClusterer;
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.map = this.markerClusterer.getMap();
this.gridSize = this.markerClusterer.getGridSize();
this.minClusterSize = this.markerClusterer.getMinimumClusterSize();
this.averageCenter = this.markerClusterer.getAverageCenter();
this.markers = [];
this.center = undefined;
this.bounds = null;
this.clusterIcon = new ClusterIcon(this, this.markerClusterer.getStyles());
}
Cluster.prototype.getSize = function () {
return this.markers.length;
};
Cluster.prototype.getMarkers = function () {
return this.markers;
};
Cluster.prototype.getCenter = function () {
return this.center;
};
Cluster.prototype.getMap = function () {
return this.map;
};
Cluster.prototype.getClusterer = function () {
return this.markerClusterer;
};
Cluster.prototype.getBounds = function () {
var bounds = new google.maps.LatLngBounds(this.center, this.center);
var markers = this.getMarkers();
for (var i = 0; i < markers.length; i++) {
var position = markers[i].getPosition();
if (position) {
bounds.extend(position);
}
}
return bounds;
};
Cluster.prototype.remove = function () {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.clusterIcon.setMap(null);
this.markers = [];
// @ts-ignore
delete this.markers;
};
Cluster.prototype.addMarker = function (marker) {
if (this.isMarkerAlreadyAdded(marker)) {
return false;
}
if (!this.center) {
var position = marker.getPosition();
if (position) {
this.center = position;
this.calculateBounds();
}
}
else {
if (this.averageCenter) {
var position = marker.getPosition();
if (position) {
var length_1 = this.markers.length + 1;
this.center = new google.maps.LatLng((this.center.lat() * (length_1 - 1) + position.lat()) / length_1, (this.center.lng() * (length_1 - 1) + position.lng()) / length_1);
this.calculateBounds();
}
}
}
marker.isAdded = true;
this.markers.push(marker);
var mCount = this.markers.length;
var maxZoom = this.markerClusterer.getMaxZoom();
if (maxZoom !== null && this.map.getZoom() > maxZoom) {
// Zoomed in past max zoom, so show the marker.
if (marker.getMap() !== this.map) {
marker.setMap(this.map);
}
}
else if (mCount < this.minClusterSize) {
// Min cluster size not reached so show the marker.
if (marker.getMap() !== this.map) {
marker.setMap(this.map);
}
}
else if (mCount === this.minClusterSize) {
// Hide the markers that were showing.
for (var i = 0; i < mCount; i++) {
this.markers[i].setMap(null);
}
}
else {
marker.setMap(null);
}
return true;
};
Cluster.prototype.isMarkerInClusterBounds = function (marker) {
if (this.bounds !== null) {
var position = marker.getPosition();
if (position) {
return this.bounds.contains(position);
}
}
return false;
};
Cluster.prototype.calculateBounds = function () {
this.bounds = this.markerClusterer.getExtendedBounds(new google.maps.LatLngBounds(this.center, this.center));
};
Cluster.prototype.updateIcon = function () {
var mCount = this.markers.length;
var maxZoom = this.markerClusterer.getMaxZoom();
if (maxZoom !== null && this.map.getZoom() > maxZoom) {
this.clusterIcon.hide();
return;
}
if (mCount < this.minClusterSize) {
// Min cluster size not yet reached.
this.clusterIcon.hide();
return;
}
if (this.center) {
this.clusterIcon.setCenter(this.center);
}
this.clusterIcon.useStyle(this.markerClusterer.getCalculator()(this.markers, this.markerClusterer.getStyles().length));
this.clusterIcon.show();
};
Cluster.prototype.isMarkerAlreadyAdded = function (marker) {
if (this.markers.includes) {
return this.markers.includes(marker);
}
else {
for (var i = 0; i < this.markers.length; i++) {
if (marker === this.markers[i]) {
return true;
}
}
}
return false;
};
return Cluster;
}());
/* global google */
/**
* Supports up to 9007199254740991 (Number.MAX_SAFE_INTEGER) markers
* which is not a problem as max array length is 4294967296 (2**32)
*/
var CALCULATOR = function CALCULATOR(markers, numStyles) {
var count = markers.length;
var numberOfDigits = count.toString().length;
var index = Math.min(numberOfDigits, numStyles);
return {
text: count.toString(),
index: index,
title: '',
};
};
var BATCH_SIZE = 2000;
var BATCH_SIZE_IE = 500;
var IMAGE_PATH = 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m';
var IMAGE_EXTENSION = 'png';
var IMAGE_SIZES = [53, 56, 66, 78, 90];
var CLUSTERER_CLASS = 'cluster';
var Clusterer = /** @class */ (function () {
function Clusterer(map, optMarkers, optOptions) {
if (optMarkers === void 0) { optMarkers = []; }
if (optOptions === void 0) { optOptions = {}; }
this.extend(Clusterer, google.maps.OverlayView);
this.markers = [];
this.clusters = [];
this.listeners = [];
this.activeMap = null;
this.ready = false;
this.gridSize = optOptions.gridSize || 60;
this.minClusterSize = optOptions.minimumClusterSize || 2;
this.maxZoom = optOptions.maxZoom || null;
this.styles = optOptions.styles || [];
this.title = optOptions.title || '';
this.zoomOnClick = true;
if (optOptions.zoomOnClick !== undefined) {
this.zoomOnClick = optOptions.zoomOnClick;
}
this.averageCenter = false;
if (optOptions.averageCenter !== undefined) {
this.averageCenter = optOptions.averageCenter;
}
this.ignoreHidden = false;
if (optOptions.ignoreHidden !== undefined) {
this.ignoreHidden = optOptions.ignoreHidden;
}
this.enableRetinaIcons = false;
if (optOptions.enableRetinaIcons !== undefined) {
this.enableRetinaIcons = optOptions.enableRetinaIcons;
}
this.imagePath = optOptions.imagePath || IMAGE_PATH;
this.imageExtension = optOptions.imageExtension || IMAGE_EXTENSION;
this.imageSizes = optOptions.imageSizes || IMAGE_SIZES;
this.calculator = optOptions.calculator || CALCULATOR;
this.batchSize = optOptions.batchSize || BATCH_SIZE;
this.batchSizeIE = optOptions.batchSizeIE || BATCH_SIZE_IE;
this.clusterClass = optOptions.clusterClass || CLUSTERER_CLASS;
if (navigator.userAgent.toLowerCase().indexOf('msie') !== -1) {
// Try to avoid IE timeout when processing a huge number of markers:
this.batchSize = this.batchSizeIE;
}
this.timerRefStatic = null;
this.setupStyles();
this.addMarkers(optMarkers, true);
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.setMap(map); // Note: this causes onAdd to be called
}
Clusterer.prototype.onAdd = function () {
var _this = this;
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.activeMap = this.getMap();
this.ready = true;
this.repaint();
// Add the map event listeners
this.listeners = [
google.maps.event.addListener(
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap(), 'zoom_changed',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
_this.resetViewport(false);
// Workaround for this Google bug: when map is at level 0 and "-" of
// zoom slider is clicked, a "zoom_changed" event is fired even though
// the map doesn't zoom out any further. In this situation, no "idle"
// event is triggered so the cluster markers that have been removed
// do not get redrawn. Same goes for a zoom in at maxZoom.
if (
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
_this.getMap().getZoom() === (_this.get('minZoom') || 0) ||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
_this.getMap().getZoom() === _this.get('maxZoom')) {
google.maps.event.trigger(_this, 'idle');
}
}),
google.maps.event.addListener(
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap(), 'idle',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
_this.redraw();
}),
];
};
// eslint-disable-next-line @getify/proper-arrows/this
Clusterer.prototype.onRemove = function () {
// Put all the managed markers back on the map:
for (var i = 0; i < this.markers.length; i++) {
if (this.markers[i].getMap() !== this.activeMap) {
this.markers[i].setMap(this.activeMap);
}
}
// Remove all clusters:
for (var i = 0; i < this.clusters.length; i++) {
this.clusters[i].remove();
}
this.clusters = [];
// Remove map event listeners:
for (var i = 0; i < this.listeners.length; i++) {
google.maps.event.removeListener(this.listeners[i]);
}
this.listeners = [];
this.activeMap = null;
this.ready = false;
};
// eslint-disable-next-line @typescript-eslint/no-empty-function
Clusterer.prototype.draw = function () { };
Clusterer.prototype.setupStyles = function () {
if (this.styles.length > 0) {
return;
}
for (var i = 0; i < this.imageSizes.length; i++) {
this.styles.push({
url: this.imagePath + (i + 1) + '.' + this.imageExtension,
height: this.imageSizes[i],
width: this.imageSizes[i],
});
}
};
Clusterer.prototype.fitMapToMarkers = function () {
var markers = this.getMarkers();
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markers.length; i++) {
var position = markers[i].getPosition();
if (position) {
bounds.extend(position);
}
}
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap().fitBounds(bounds);
};
Clusterer.prototype.getGridSize = function () {
return this.gridSize;
};
Clusterer.prototype.setGridSize = function (gridSize) {
this.gridSize = gridSize;
};
Clusterer.prototype.getMinimumClusterSize = function () {
return this.minClusterSize;
};
Clusterer.prototype.setMinimumClusterSize = function (minimumClusterSize) {
this.minClusterSize = minimumClusterSize;
};
Clusterer.prototype.getMaxZoom = function () {
return this.maxZoom;
};
Clusterer.prototype.setMaxZoom = function (maxZoom) {
this.maxZoom = maxZoom;
};
Clusterer.prototype.getStyles = function () {
return this.styles;
};
Clusterer.prototype.setStyles = function (styles) {
this.styles = styles;
};
Clusterer.prototype.getTitle = function () {
return this.title;
};
Clusterer.prototype.setTitle = function (title) {
this.title = title;
};
Clusterer.prototype.getZoomOnClick = function () {
return this.zoomOnClick;
};
Clusterer.prototype.setZoomOnClick = function (zoomOnClick) {
this.zoomOnClick = zoomOnClick;
};
Clusterer.prototype.getAverageCenter = function () {
return this.averageCenter;
};
Clusterer.prototype.setAverageCenter = function (averageCenter) {
this.averageCenter = averageCenter;
};
Clusterer.prototype.getIgnoreHidden = function () {
return this.ignoreHidden;
};
Clusterer.prototype.setIgnoreHidden = function (ignoreHidden) {
this.ignoreHidden = ignoreHidden;
};
Clusterer.prototype.getEnableRetinaIcons = function () {
return this.enableRetinaIcons;
};
Clusterer.prototype.setEnableRetinaIcons = function (enableRetinaIcons) {
this.enableRetinaIcons = enableRetinaIcons;
};
Clusterer.prototype.getImageExtension = function () {
return this.imageExtension;
};
Clusterer.prototype.setImageExtension = function (imageExtension) {
this.imageExtension = imageExtension;
};
Clusterer.prototype.getImagePath = function () {
return this.imagePath;
};
Clusterer.prototype.setImagePath = function (imagePath) {
this.imagePath = imagePath;
};
Clusterer.prototype.getImageSizes = function () {
return this.imageSizes;
};
Clusterer.prototype.setImageSizes = function (imageSizes) {
this.imageSizes = imageSizes;
};
Clusterer.prototype.getCalculator = function () {
return this.calculator;
};
Clusterer.prototype.setCalculator = function (calculator) {
this.calculator = calculator;
};
Clusterer.prototype.getBatchSizeIE = function () {
return this.batchSizeIE;
};
Clusterer.prototype.setBatchSizeIE = function (batchSizeIE) {
this.batchSizeIE = batchSizeIE;
};
Clusterer.prototype.getClusterClass = function () {
return this.clusterClass;
};
Clusterer.prototype.setClusterClass = function (clusterClass) {
this.clusterClass = clusterClass;
};
Clusterer.prototype.getMarkers = function () {
return this.markers;
};
Clusterer.prototype.getTotalMarkers = function () {
return this.markers.length;
};
Clusterer.prototype.getClusters = function () {
return this.clusters;
};
Clusterer.prototype.getTotalClusters = function () {
return this.clusters.length;
};
Clusterer.prototype.addMarker = function (marker, optNoDraw) {
this.pushMarkerTo(marker);
if (!optNoDraw) {
this.redraw();
}
};
Clusterer.prototype.addMarkers = function (markers, optNoDraw) {
for (var key in markers) {
if (markers.hasOwnProperty(key)) {
this.pushMarkerTo(markers[key]);
}
}
if (!optNoDraw) {
this.redraw();
}
};
Clusterer.prototype.pushMarkerTo = function (marker) {
var _this = this;
// If the marker is draggable add a listener so we can update the clusters on the dragend:
if (marker.getDraggable()) {
// eslint-disable-next-line @getify/proper-arrows/name, @getify/proper-arrows/this
google.maps.event.addListener(marker, 'dragend', function () {
if (_this.ready) {
marker.isAdded = false;
_this.repaint();
}
});
}
marker.isAdded = false;
this.markers.push(marker);
};
Clusterer.prototype.removeMarker_ = function (marker) {
var index = -1;
if (this.markers.indexOf) {
index = this.markers.indexOf(marker);
}
else {
for (var i = 0; i < this.markers.length; i++) {
if (marker === this.markers[i]) {
index = i;
break;
}
}
}
if (index === -1) {
// Marker is not in our list of markers, so do nothing:
return false;
}
marker.setMap(null);
this.markers.splice(index, 1); // Remove the marker from the list of managed markers
return true;
};
Clusterer.prototype.removeMarker = function (marker, optNoDraw) {
var removed = this.removeMarker_(marker);
if (!optNoDraw && removed) {
this.repaint();
}
return removed;
};
Clusterer.prototype.removeMarkers = function (markers, optNoDraw) {
var removed = false;
for (var i = 0; i < markers.length; i++) {
removed = removed || this.removeMarker_(markers[i]);
}
if (!optNoDraw && removed) {
this.repaint();
}
return removed;
};
Clusterer.prototype.clearMarkers = function () {
this.resetViewport(true);
this.markers = [];
};
Clusterer.prototype.repaint = function () {
var oldClusters = this.clusters.slice();
this.clusters = [];
this.resetViewport(false);
this.redraw();
// Remove the old clusters.
// Do it in a timeout to prevent blinking effect.
setTimeout(function timeout() {
for (var i = 0; i < oldClusters.length; i++) {
oldClusters[i].remove();
}
}, 0);
};
Clusterer.prototype.getExtendedBounds = function (bounds) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
var projection = this.getProjection();
// Convert the points to pixels and the extend out by the grid size.
var trPix = projection.fromLatLngToDivPixel(
// Turn the bounds into latlng.
new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getNorthEast().lng()));
trPix.x += this.gridSize;
trPix.y -= this.gridSize;
var blPix = projection.fromLatLngToDivPixel(
// Turn the bounds into latlng.
new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng()));
blPix.x -= this.gridSize;
blPix.y += this.gridSize;
// Extend the bounds to contain the new bounds.
bounds.extend(
// Convert the pixel points back to LatLng nw
projection.fromDivPixelToLatLng(trPix));
bounds.extend(
// Convert the pixel points back to LatLng sw
projection.fromDivPixelToLatLng(blPix));
return bounds;
};
Clusterer.prototype.redraw = function () {
// Redraws all the clusters.
this.createClusters(0);
};
Clusterer.prototype.resetViewport = function (optHide) {
// Remove all the clusters
for (var i = 0; i < this.clusters.length; i++) {
this.clusters[i].remove();
}
this.clusters = [];
// Reset the markers to not be added and to be removed from the map.
for (var i = 0; i < this.markers.length; i++) {
var marker = this.markers[i];
marker.isAdded = false;
if (optHide) {
marker.setMap(null);
}
}
};
Clusterer.prototype.distanceBetweenPoints = function (p1, p2) {
var R = 6371; // Radius of the Earth in km
var dLat = ((p2.lat() - p1.lat()) * Math.PI) / 180;
var dLon = ((p2.lng() - p1.lng()) * Math.PI) / 180;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos((p1.lat() * Math.PI) / 180) *
Math.cos((p2.lat() * Math.PI) / 180) *
Math.sin(dLon / 2) *
Math.sin(dLon / 2);
return R * (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)));
};
Clusterer.prototype.isMarkerInBounds = function (marker, bounds) {
var position = marker.getPosition();
if (position) {
return bounds.contains(position);
}
return false;
};
Clusterer.prototype.addToClosestCluster = function (marker) {
var cluster;
var distance = 40000; // Some large number
var clusterToAddTo = null;
for (var i = 0; i < this.clusters.length; i++) {
cluster = this.clusters[i];
var center = cluster.getCenter();
var position = marker.getPosition();
if (center && position) {
var d = this.distanceBetweenPoints(center, position);
if (d < distance) {
distance = d;
clusterToAddTo = cluster;
}
}
}
if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {
clusterToAddTo.addMarker(marker);
}
else {
cluster = new Cluster(this);
cluster.addMarker(marker);
this.clusters.push(cluster);
}
};
Clusterer.prototype.createClusters = function (iFirst) {
var _this = this;
if (!this.ready) {
return;
}
// Cancel previous batch processing if we're working on the first batch:
if (iFirst === 0) {
/**
* This event is fired when the <code>Clusterer</code> begins
* clustering markers.
* @name Clusterer#clusteringbegin
* @param {Clusterer} mc The Clusterer whose markers are being clustered.
* @event
*/
google.maps.event.trigger(this, 'clusteringbegin', this);
if (this.timerRefStatic !== null) {
window.clearTimeout(this.timerRefStatic);
// @ts-ignore
delete this.timerRefStatic;
}
}
// Get our current map view bounds.
// Create a new bounds object so we don't affect the map.
//
// See Comments 9 & 11 on Issue 3651 relating to this workaround for a Google Maps bug:
var mapBounds =
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap().getZoom() > 3
? new google.maps.LatLngBounds(
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap()
.getBounds()
.getSouthWest(),
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap()
.getBounds()
.getNorthEast())
: new google.maps.LatLngBounds(new google.maps.LatLng(85.02070771743472, -178.48388434375), new google.maps.LatLng(-85.08136444384544, 178.00048865625));
var bounds = this.getExtendedBounds(mapBounds);
var iLast = Math.min(iFirst + this.batchSize, this.markers.length);
for (var i = iFirst; i < iLast; i++) {
var marker = this.markers[i];
if (!marker.isAdded && this.isMarkerInBounds(marker, bounds)) {
if (!this.ignoreHidden || (this.ignoreHidden && marker.getVisible())) {
this.addToClosestCluster(marker);
}
}
}
if (iLast < this.markers.length) {
this.timerRefStatic = window.setTimeout(
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
_this.createClusters(iLast);
}, 0);
}
else {
this.timerRefStatic = null;
/**
* This event is fired when the <code>Clusterer</code> stops
* clustering markers.
* @name Clusterer#clusteringend
* @param {Clusterer} mc The Clusterer whose markers are being clustered.
* @event
*/
google.maps.event.trigger(this, 'clusteringend', this);
for (var i = 0; i < this.clusters.length; i++) {
this.clusters[i].updateIcon();
}
}
};
Clusterer.prototype.extend = function (obj1, obj2) {
return function applyExtend(object) {
// eslint-disable-next-line guard-for-in
for (var property in object.prototype) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.prototype[property] = object.prototype[property];
}
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
return this;
}.apply(obj1, [obj2]);
};
return Clusterer;
}());
/* global google */
/**
* Supports up to 9007199254740991 (Number.MAX_SAFE_INTEGER) markers
* which is not a problem as max array length is 4294967296 (2**32)
*/
var CALCULATOR = function CALCULATOR(markers, numStyles) {
var count = markers.length;
var numberOfDigits = count.toString().length;
var index = Math.min(numberOfDigits, numStyles);
return {
text: count.toString(),
index: index,
title: '',
};
};
var BATCH_SIZE = 2000;
var BATCH_SIZE_IE = 500;
var IMAGE_PATH = 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m';
var IMAGE_EXTENSION = 'png';
var IMAGE_SIZES = [53, 56, 66, 78, 90];
var CLUSTERER_CLASS = 'cluster';
var Clusterer = /** @class */ (function () {
function Clusterer(map, optMarkers, optOptions) {
if (optMarkers === void 0) { optMarkers = []; }
if (optOptions === void 0) { optOptions = {}; }
this.extend(Clusterer, google.maps.OverlayView);
this.markers = [];
this.clusters = [];
this.listeners = [];
this.activeMap = null;
this.ready = false;
this.gridSize = optOptions.gridSize || 60;
this.minClusterSize = optOptions.minimumClusterSize || 2;
this.maxZoom = optOptions.maxZoom || null;
this.styles = optOptions.styles || [];
this.title = optOptions.title || '';
this.zoomOnClick = true;
if (optOptions.zoomOnClick !== undefined) {
this.zoomOnClick = optOptions.zoomOnClick;
}
this.averageCenter = false;
if (optOptions.averageCenter !== undefined) {
this.averageCenter = optOptions.averageCenter;
}
this.ignoreHidden = false;
if (optOptions.ignoreHidden !== undefined) {
this.ignoreHidden = optOptions.ignoreHidden;
}
this.enableRetinaIcons = false;
if (optOptions.enableRetinaIcons !== undefined) {
this.enableRetinaIcons = optOptions.enableRetinaIcons;
}
this.imagePath = optOptions.imagePath || IMAGE_PATH;
this.imageExtension = optOptions.imageExtension || IMAGE_EXTENSION;
this.imageSizes = optOptions.imageSizes || IMAGE_SIZES;
this.calculator = optOptions.calculator || CALCULATOR;
this.batchSize = optOptions.batchSize || BATCH_SIZE;
this.batchSizeIE = optOptions.batchSizeIE || BATCH_SIZE_IE;
this.clusterClass = optOptions.clusterClass || CLUSTERER_CLASS;
if (navigator.userAgent.toLowerCase().indexOf('msie') !== -1) {
// Try to avoid IE timeout when processing a huge number of markers:
this.batchSize = this.batchSizeIE;
}
this.timerRefStatic = null;
this.setupStyles();
this.addMarkers(optMarkers, true);
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.setMap(map); // Note: this causes onAdd to be called
}
Clusterer.prototype.onAdd = function () {
var _this = this;
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.activeMap = this.getMap();
this.ready = true;
this.repaint();
// Add the map event listeners
this.listeners = [
google.maps.event.addListener(
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap(), 'zoom_changed',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
_this.resetViewport(false);
// Workaround for this Google bug: when map is at level 0 and "-" of
// zoom slider is clicked, a "zoom_changed" event is fired even though
// the map doesn't zoom out any further. In this situation, no "idle"
// event is triggered so the cluster markers that have been removed
// do not get redrawn. Same goes for a zoom in at maxZoom.
if (
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
_this.getMap().getZoom() === (_this.get('minZoom') || 0) ||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
_this.getMap().getZoom() === _this.get('maxZoom')) {
google.maps.event.trigger(_this, 'idle');
}
}),
google.maps.event.addListener(
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap(), 'idle',
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
_this.redraw();
}),
];
};
// eslint-disable-next-line @getify/proper-arrows/this
Clusterer.prototype.onRemove = function () {
// Put all the managed markers back on the map:
for (var i = 0; i < this.markers.length; i++) {
if (this.markers[i].getMap() !== this.activeMap) {
this.markers[i].setMap(this.activeMap);
}
}
// Remove all clusters:
for (var i = 0; i < this.clusters.length; i++) {
this.clusters[i].remove();
}
this.clusters = [];
// Remove map event listeners:
for (var i = 0; i < this.listeners.length; i++) {
google.maps.event.removeListener(this.listeners[i]);
}
this.listeners = [];
this.activeMap = null;
this.ready = false;
};
// eslint-disable-next-line @typescript-eslint/no-empty-function
Clusterer.prototype.draw = function () { };
Clusterer.prototype.setupStyles = function () {
if (this.styles.length > 0) {
return;
}
for (var i = 0; i < this.imageSizes.length; i++) {
this.styles.push({
url: this.imagePath + (i + 1) + '.' + this.imageExtension,
height: this.imageSizes[i],
width: this.imageSizes[i],
});
}
};
Clusterer.prototype.fitMapToMarkers = function () {
var markers = this.getMarkers();
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markers.length; i++) {
var position = markers[i].getPosition();
if (position) {
bounds.extend(position);
}
}
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap().fitBounds(bounds);
};
Clusterer.prototype.getGridSize = function () {
return this.gridSize;
};
Clusterer.prototype.setGridSize = function (gridSize) {
this.gridSize = gridSize;
};
Clusterer.prototype.getMinimumClusterSize = function () {
return this.minClusterSize;
};
Clusterer.prototype.setMinimumClusterSize = function (minimumClusterSize) {
this.minClusterSize = minimumClusterSize;
};
Clusterer.prototype.getMaxZoom = function () {
return this.maxZoom;
};
Clusterer.prototype.setMaxZoom = function (maxZoom) {
this.maxZoom = maxZoom;
};
Clusterer.prototype.getStyles = function () {
return this.styles;
};
Clusterer.prototype.setStyles = function (styles) {
this.styles = styles;
};
Clusterer.prototype.getTitle = function () {
return this.title;
};
Clusterer.prototype.setTitle = function (title) {
this.title = title;
};
Clusterer.prototype.getZoomOnClick = function () {
return this.zoomOnClick;
};
Clusterer.prototype.setZoomOnClick = function (zoomOnClick) {
this.zoomOnClick = zoomOnClick;
};
Clusterer.prototype.getAverageCenter = function () {
return this.averageCenter;
};
Clusterer.prototype.setAverageCenter = function (averageCenter) {
this.averageCenter = averageCenter;
};
Clusterer.prototype.getIgnoreHidden = function () {
return this.ignoreHidden;
};
Clusterer.prototype.setIgnoreHidden = function (ignoreHidden) {
this.ignoreHidden = ignoreHidden;
};
Clusterer.prototype.getEnableRetinaIcons = function () {
return this.enableRetinaIcons;
};
Clusterer.prototype.setEnableRetinaIcons = function (enableRetinaIcons) {
this.enableRetinaIcons = enableRetinaIcons;
};
Clusterer.prototype.getImageExtension = function () {
return this.imageExtension;
};
Clusterer.prototype.setImageExtension = function (imageExtension) {
this.imageExtension = imageExtension;
};
Clusterer.prototype.getImagePath = function () {
return this.imagePath;
};
Clusterer.prototype.setImagePath = function (imagePath) {
this.imagePath = imagePath;
};
Clusterer.prototype.getImageSizes = function () {
return this.imageSizes;
};
Clusterer.prototype.setImageSizes = function (imageSizes) {
this.imageSizes = imageSizes;
};
Clusterer.prototype.getCalculator = function () {
return this.calculator;
};
Clusterer.prototype.setCalculator = function (calculator) {
this.calculator = calculator;
};
Clusterer.prototype.getBatchSizeIE = function () {
return this.batchSizeIE;
};
Clusterer.prototype.setBatchSizeIE = function (batchSizeIE) {
this.batchSizeIE = batchSizeIE;
};
Clusterer.prototype.getClusterClass = function () {
return this.clusterClass;
};
Clusterer.prototype.setClusterClass = function (clusterClass) {
this.clusterClass = clusterClass;
};
Clusterer.prototype.getMarkers = function () {
return this.markers;
};
Clusterer.prototype.getTotalMarkers = function () {
return this.markers.length;
};
Clusterer.prototype.getClusters = function () {
return this.clusters;
};
Clusterer.prototype.getTotalClusters = function () {
return this.clusters.length;
};
Clusterer.prototype.addMarker = function (marker, optNoDraw) {
this.pushMarkerTo(marker);
if (!optNoDraw) {
this.redraw();
}
};
Clusterer.prototype.addMarkers = function (markers, optNoDraw) {
for (var key in markers) {
if (markers.hasOwnProperty(key)) {
this.pushMarkerTo(markers[key]);
}
}
if (!optNoDraw) {
this.redraw();
}
};
Clusterer.prototype.pushMarkerTo = function (marker) {
var _this = this;
// If the marker is draggable add a listener so we can update the clusters on the dragend:
if (marker.getDraggable()) {
// eslint-disable-next-line @getify/proper-arrows/name, @getify/proper-arrows/this
google.maps.event.addListener(marker, 'dragend', function () {
if (_this.ready) {
marker.isAdded = false;
_this.repaint();
}
});
}
marker.isAdded = false;
this.markers.push(marker);
};
Clusterer.prototype.removeMarker_ = function (marker) {
var index = -1;
if (this.markers.indexOf) {
index = this.markers.indexOf(marker);
}
else {
for (var i = 0; i < this.markers.length; i++) {
if (marker === this.markers[i]) {
index = i;
break;
}
}
}
if (index === -1) {
// Marker is not in our list of markers, so do nothing:
return false;
}
marker.setMap(null);
this.markers.splice(index, 1); // Remove the marker from the list of managed markers
return true;
};
Clusterer.prototype.removeMarker = function (marker, optNoDraw) {
var removed = this.removeMarker_(marker);
if (!optNoDraw && removed) {
this.repaint();
}
return removed;
};
Clusterer.prototype.removeMarkers = function (markers, optNoDraw) {
var removed = false;
for (var i = 0; i < markers.length; i++) {
removed = removed || this.removeMarker_(markers[i]);
}
if (!optNoDraw && removed) {
this.repaint();
}
return removed;
};
Clusterer.prototype.clearMarkers = function () {
this.resetViewport(true);
this.markers = [];
};
Clusterer.prototype.repaint = function () {
var oldClusters = this.clusters.slice();
this.clusters = [];
this.resetViewport(false);
this.redraw();
// Remove the old clusters.
// Do it in a timeout to prevent blinking effect.
setTimeout(function timeout() {
for (var i = 0; i < oldClusters.length; i++) {
oldClusters[i].remove();
}
}, 0);
};
Clusterer.prototype.getExtendedBounds = function (bounds) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
var projection = this.getProjection();
// Convert the points to pixels and the extend out by the grid size.
var trPix = projection.fromLatLngToDivPixel(
// Turn the bounds into latlng.
new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getNorthEast().lng()));
trPix.x += this.gridSize;
trPix.y -= this.gridSize;
var blPix = projection.fromLatLngToDivPixel(
// Turn the bounds into latlng.
new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng()));
blPix.x -= this.gridSize;
blPix.y += this.gridSize;
// Extend the bounds to contain the new bounds.
bounds.extend(
// Convert the pixel points back to LatLng nw
projection.fromDivPixelToLatLng(trPix));
bounds.extend(
// Convert the pixel points back to LatLng sw
projection.fromDivPixelToLatLng(blPix));
return bounds;
};
Clusterer.prototype.redraw = function () {
// Redraws all the clusters.
this.createClusters(0);
};
Clusterer.prototype.resetViewport = function (optHide) {
// Remove all the clusters
for (var i = 0; i < this.clusters.length; i++) {
this.clusters[i].remove();
}
this.clusters = [];
// Reset the markers to not be added and to be removed from the map.
for (var i = 0; i < this.markers.length; i++) {
var marker = this.markers[i];
marker.isAdded = false;
if (optHide) {
marker.setMap(null);
}
}
};
Clusterer.prototype.distanceBetweenPoints = function (p1, p2) {
var R = 6371; // Radius of the Earth in km
var dLat = ((p2.lat() - p1.lat()) * Math.PI) / 180;
var dLon = ((p2.lng() - p1.lng()) * Math.PI) / 180;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos((p1.lat() * Math.PI) / 180) *
Math.cos((p2.lat() * Math.PI) / 180) *
Math.sin(dLon / 2) *
Math.sin(dLon / 2);
return R * (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)));
};
Clusterer.prototype.isMarkerInBounds = function (marker, bounds) {
var position = marker.getPosition();
if (position) {
return bounds.contains(position);
}
return false;
};
Clusterer.prototype.addToClosestCluster = function (marker) {
var cluster;
var distance = 40000; // Some large number
var clusterToAddTo = null;
for (var i = 0; i < this.clusters.length; i++) {
cluster = this.clusters[i];
var center = cluster.getCenter();
var position = marker.getPosition();
if (center && position) {
var d = this.distanceBetweenPoints(center, position);
if (d < distance) {
distance = d;
clusterToAddTo = cluster;
}
}
}
if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {
clusterToAddTo.addMarker(marker);
}
else {
cluster = new Cluster(this);
cluster.addMarker(marker);
this.clusters.push(cluster);
}
};
Clusterer.prototype.createClusters = function (iFirst) {
var _this = this;
if (!this.ready) {
return;
}
// Cancel previous batch processing if we're working on the first batch:
if (iFirst === 0) {
/**
* This event is fired when the <code>Clusterer</code> begins
* clustering markers.
* @name Clusterer#clusteringbegin
* @param {Clusterer} mc The Clusterer whose markers are being clustered.
* @event
*/
google.maps.event.trigger(this, 'clusteringbegin', this);
if (this.timerRefStatic !== null) {
window.clearTimeout(this.timerRefStatic);
// @ts-ignore
delete this.timerRefStatic;
}
}
// Get our current map view bounds.
// Create a new bounds object so we don't affect the map.
//
// See Comments 9 & 11 on Issue 3651 relating to this workaround for a Google Maps bug:
var mapBounds =
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap().getZoom() > 3
? new google.maps.LatLngBounds(
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap()
.getBounds()
.getSouthWest(),
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.getMap()
.getBounds()
.getNorthEast())
: new google.maps.LatLngBounds(new google.maps.LatLng(85.02070771743472, -178.48388434375), new google.maps.LatLng(-85.08136444384544, 178.00048865625));
var bounds = this.getExtendedBounds(mapBounds);
var iLast = Math.min(iFirst + this.batchSize, this.markers.length);
for (var i = iFirst; i < iLast; i++) {
var marker = this.markers[i];
if (!marker.isAdded && this.isMarkerInBounds(marker, bounds)) {
if (!this.ignoreHidden || (this.ignoreHidden && marker.getVisible())) {
this.addToClosestCluster(marker);
}
}
}
if (iLast < this.markers.length) {
this.timerRefStatic = window.setTimeout(
// eslint-disable-next-line @getify/proper-arrows/this, @getify/proper-arrows/name
function () {
_this.createClusters(iLast);
}, 0);
}
else {
this.timerRefStatic = null;
/**
* This event is fired when the <code>Clusterer</code> stops
* clustering markers.
* @name Clusterer#clusteringend
* @param {Clusterer} mc The Clusterer whose markers are being clustered.
* @event
*/
google.maps.event.trigger(this, 'clusteringend', this);
for (var i = 0; i < this.clusters.length; i++) {
this.clusters[i].updateIcon();
}
}
};
Clusterer.prototype.extend = function (obj1, obj2) {
return function applyExtend(object) {
// eslint-disable-next-line guard-for-in
for (var property in object.prototype) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.prototype[property] = object.prototype[property];
}
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
return this;
}.apply(obj1, [obj2]);
};
return Clusterer;
}());
exports.Cluster = Cluster;
exports.ClusterIcon = ClusterIcon;
exports.Clusterer = Clusterer;
exports.Cluster = Cluster;
exports.ClusterIcon = ClusterIcon;
exports.Clusterer = Clusterer;
Object.defineProperty(exports, '__esModule', { value: true });
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=umd.js.map
{
"name": "@react-google-maps/marker-clusterer",
"sideEffects": false,
"version": "2.3.0",
"version": "2.3.1",
"description": "Marker Clusterer for React.js Google Maps API",

@@ -59,8 +59,9 @@ "license": "MIT",

"@rollup/plugin-node-resolve": "13.0.4",
"@rollup/plugin-typescript": "8.2.5",
"@types/babel-types": "7.0.11",
"@types/googlemaps": "3.43.3",
"@types/jest": "27.0.1",
"@types/react-dom": "17.0.9",
"@typescript-eslint/eslint-plugin": "4.31.1",
"@typescript-eslint/parser": "4.31.1",
"awesome-typescript-loader": "5.2.1",
"eslint": "7.32.0",

@@ -93,4 +94,4 @@ "eslint-config-standard": "16.0.3",

"rollup": "2.56.3",
"rollup-plugin-dts": "4.0.0",
"rollup-plugin-terser": "7.0.2",
"rollup-plugin-ts": "1.4.2",
"ts-jest": "27.0.5",

@@ -97,0 +98,0 @@ "typescript": "4.4.3"

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc