diff --git a/src/algorithms/grid.ts b/src/algorithms/grid.ts index 6757f55f..5b6fb6c3 100644 --- a/src/algorithms/grid.ts +++ b/src/algorithms/grid.ts @@ -115,12 +115,18 @@ export class GridAlgorithm extends AbstractViewportAlgorithm { ): void { let maxDistance = this.maxDistance; // Some large number let cluster: Cluster = null; + const position = MarkerUtils.getPosition(marker); + + if (position === null) { + // Marker has no position, which makes it invisible and not part of the cluster + return; + } for (let i = 0; i < this.clusters.length; i++) { const candidate = this.clusters[i]; const distance = distanceBetweenPoints( candidate.bounds.getCenter().toJSON(), - MarkerUtils.getPosition(marker).toJSON() + position.toJSON() ); if (distance < maxDistance) { @@ -135,7 +141,7 @@ export class GridAlgorithm extends AbstractViewportAlgorithm { cluster.bounds, projection, this.gridSize - ).contains(MarkerUtils.getPosition(marker)) + ).contains(position) ) { cluster.push(marker); } else { diff --git a/src/algorithms/supercluster.ts b/src/algorithms/supercluster.ts index 75336882..d28650d3 100644 --- a/src/algorithms/supercluster.ts +++ b/src/algorithms/supercluster.ts @@ -59,6 +59,10 @@ export class SuperClusterAlgorithm extends AbstractAlgorithm { const points = this.markers.map((marker) => { const position = MarkerUtils.getPosition(marker); + if (!position) { + return null; + } + const coordinates = [position.lng(), position.lat()]; return { type: "Feature" as const, @@ -69,7 +73,7 @@ export class SuperClusterAlgorithm extends AbstractAlgorithm { properties: { marker }, }; }); - this.superCluster.load(points); + this.superCluster.load(points.filter((p) => p != null)); } if (!changed) { diff --git a/src/algorithms/superviewport.ts b/src/algorithms/superviewport.ts index 0f3b6c77..494ff52a 100644 --- a/src/algorithms/superviewport.ts +++ b/src/algorithms/superviewport.ts @@ -85,6 +85,10 @@ export class SuperClusterViewportAlgorithm extends AbstractViewportAlgorithm { const points = this.markers.map((marker) => { const position = MarkerUtils.getPosition(marker); + if (!position) { + return null; + } + const coordinates = [position.lng(), position.lat()]; return { type: "Feature" as const, @@ -95,7 +99,7 @@ export class SuperClusterViewportAlgorithm extends AbstractViewportAlgorithm { properties: { marker }, }; }); - this.superCluster.load(points); + this.superCluster.load(points.filter((p) => p != null)); } if (changed) { diff --git a/src/algorithms/utils.ts b/src/algorithms/utils.ts index 4e727c19..f9e22058 100644 --- a/src/algorithms/utils.ts +++ b/src/algorithms/utils.ts @@ -36,9 +36,10 @@ export const filterMarkersToPaddedViewport = ( mapCanvasProjection, viewportPaddingPixels ); - return markers.filter((marker) => - extendedMapBounds.contains(MarkerUtils.getPosition(marker)) - ); + return markers.filter((marker) => { + const position = MarkerUtils.getPosition(marker); + return position ? extendedMapBounds.contains(position) : false; + }); }; /** diff --git a/src/cluster.ts b/src/cluster.ts index faacd456..169d184f 100644 --- a/src/cluster.ts +++ b/src/cluster.ts @@ -45,7 +45,10 @@ export class Cluster { const bounds = new google.maps.LatLngBounds(this._position, this._position); for (const marker of this.markers) { - bounds.extend(MarkerUtils.getPosition(marker)); + const position = MarkerUtils.getPosition(marker); + if (position) { + bounds.extend(position); + } } return bounds; } diff --git a/src/marker-utils.ts b/src/marker-utils.ts index a28f3b5b..f3a44c72 100644 --- a/src/marker-utils.ts +++ b/src/marker-utils.ts @@ -50,7 +50,7 @@ export class MarkerUtils { } } - public static getPosition(marker: Marker): google.maps.LatLng { + public static getPosition(marker: Marker): google.maps.LatLng | null { // SuperClusterAlgorithm.calculate expects a LatLng instance so we fake it for Adv Markers if (this.isAdvancedMarker(marker)) { if (marker.position) { @@ -65,7 +65,7 @@ export class MarkerUtils { ); } } - return new google.maps.LatLng(null); + return null; } return marker.getPosition(); } @@ -73,13 +73,14 @@ export class MarkerUtils { public static getVisible(marker: Marker) { if (this.isAdvancedMarker(marker)) { /** - * Always return true for Advanced Markers because the clusterer - * uses getVisible as a way to count legacy markers not as an actual - * indicator of visibility for some reason. Even when markers are hidden - * Marker.getVisible returns `true` and this is used to set the marker count - * on the cluster. See the behavior of Cluster.count + * As per google.maps.marker.AdvancedMarkerElement documentation: + * An AdvancedMarkerElement may be constructed without a position, + * but will not be displayed until its position is provided. + * + * The same goes for the map property. But in case of clustering this + * is always set to null as we don't want to show the marker on the map. */ - return true; + return marker.position !== null; } return marker.getVisible(); }