@react-google-maps/marker-clusterer 2.10.1 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Clusterer.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  /* global google */
2
2
  /* eslint-disable filenames/match-regex */
3
3
  import { Cluster } from './Cluster'
4
+ import { ClusterIcon } from './ClusterIcon'
4
5
 
5
6
  import {
6
7
  MarkerExtended,
@@ -44,7 +45,7 @@ const IMAGE_SIZES = [53, 56, 66, 78, 90]
44
45
 
45
46
  const CLUSTERER_CLASS = 'cluster'
46
47
 
47
- export class Clusterer {
48
+ export class Clusterer extends google.maps.OverlayView {
48
49
  markers: MarkerExtended[]
49
50
  clusters: Cluster[]
50
51
  listeners: google.maps.MapsEventListener[]
@@ -73,6 +74,8 @@ export class Clusterer {
73
74
  optMarkers: MarkerExtended[] = [],
74
75
  optOptions: ClustererOptions = {}
75
76
  ) {
77
+ super()
78
+
76
79
  this.extend(Clusterer, google.maps.OverlayView)
77
80
 
78
81
  this.markers = []
@@ -139,51 +142,51 @@ export class Clusterer {
139
142
  this.setMap(map) // Note: this causes onAdd to be called
140
143
  }
141
144
 
145
+ onZoomChanged() {
146
+ this.resetViewport(false)
147
+
148
+ // Workaround for this Google bug: when map is at level 0 and "-" of
149
+ // zoom slider is clicked, a "zoom_changed" event is fired even though
150
+ // the map doesn't zoom out any further. In this situation, no "idle"
151
+ // event is triggered so the cluster markers that have been removed
152
+ // do not get redrawn. Same goes for a zoom in at maxZoom.
153
+ if (
154
+ this.getMap()?.getZoom() === (this.get('minZoom') || 0) ||
155
+
156
+ this.getMap()?.getZoom() === this.get('maxZoom')
157
+ ) {
158
+ google.maps.event.trigger(this, 'idle')
159
+ }
160
+ }
161
+
162
+ onIdle() {
163
+ this.redraw()
164
+ }
165
+
142
166
  onAdd() {
143
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
144
- // @ts-ignore
145
- this.activeMap = this.getMap()
167
+ const map = this.getMap()
168
+
169
+ this.activeMap = map
146
170
 
147
171
  this.ready = true
148
172
 
149
173
  this.repaint()
150
174
 
151
- // Add the map event listeners
152
- this.listeners = [
153
- google.maps.event.addListener(
154
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
155
- // @ts-ignore
156
- this.getMap(),
157
- 'zoom_changed',
158
- () => {
159
- this.resetViewport(false)
160
- // Workaround for this Google bug: when map is at level 0 and "-" of
161
- // zoom slider is clicked, a "zoom_changed" event is fired even though
162
- // the map doesn't zoom out any further. In this situation, no "idle"
163
- // event is triggered so the cluster markers that have been removed
164
- // do not get redrawn. Same goes for a zoom in at maxZoom.
165
- if (
166
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
167
- // @ts-ignore
168
- this.getMap().getZoom() === (this.get('minZoom') || 0) ||
169
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
170
- // @ts-ignore
171
- this.getMap().getZoom() === this.get('maxZoom')
172
- ) {
173
- google.maps.event.trigger(this, 'idle')
174
- }
175
- }
176
- ),
177
- google.maps.event.addListener(
178
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
179
- // @ts-ignore
180
- this.getMap(),
181
- 'idle',
182
- () => {
183
- this.redraw()
184
- }
185
- ),
186
- ]
175
+ if (map !== null) {
176
+ // Add the map event listeners
177
+ this.listeners = [
178
+ google.maps.event.addListener(
179
+ map,
180
+ 'zoom_changed',
181
+ this.onZoomChanged
182
+ ),
183
+ google.maps.event.addListener(
184
+ map,
185
+ 'idle',
186
+ this.onIdle
187
+ ),
188
+ ]
189
+ }
187
190
  }
188
191
 
189
192
  onRemove() {
@@ -505,27 +508,43 @@ export class Clusterer {
505
508
  new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getNorthEast().lng())
506
509
  )
507
510
 
508
- trPix.x += this.gridSize
509
- trPix.y -= this.gridSize
511
+ if (trPix !== null) {
512
+ trPix.x += this.gridSize
513
+ trPix.y -= this.gridSize
514
+ }
510
515
 
511
516
  const blPix = projection.fromLatLngToDivPixel(
512
517
  // Turn the bounds into latlng.
513
518
  new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng())
514
519
  )
515
520
 
516
- blPix.x -= this.gridSize
517
- blPix.y += this.gridSize
521
+ if (blPix !== null) {
522
+ blPix.x -= this.gridSize
523
+ blPix.y += this.gridSize
524
+ }
525
+
518
526
 
519
527
  // Extend the bounds to contain the new bounds.
520
- bounds.extend(
528
+ if (trPix !== null) {
521
529
  // Convert the pixel points back to LatLng nw
522
- projection.fromDivPixelToLatLng(trPix)
523
- )
530
+ const point1 = projection.fromDivPixelToLatLng(trPix)
524
531
 
525
- bounds.extend(
532
+ if (point1 !== null) {
533
+ bounds.extend(point1)
534
+ }
535
+ }
536
+
537
+ if (blPix !== null) {
526
538
  // Convert the pixel points back to LatLng sw
527
- projection.fromDivPixelToLatLng(blPix)
528
- )
539
+ const point2 = projection.fromDivPixelToLatLng(blPix)
540
+
541
+ if (point2 !== null) {
542
+ bounds.extend(
543
+ point2
544
+ )
545
+ }
546
+ }
547
+
529
548
 
530
549
  return bounds
531
550
  }
@@ -642,6 +661,10 @@ export class Clusterer {
642
661
  }
643
662
  }
644
663
 
664
+ const map = this.getMap()
665
+
666
+ const bounds = map !== null && 'getBounds' in map ? map.getBounds() : null
667
+
645
668
  // Get our current map view bounds.
646
669
  // Create a new bounds object so we don't affect the map.
647
670
  //
@@ -649,32 +672,24 @@ export class Clusterer {
649
672
  const mapBounds =
650
673
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
651
674
  // @ts-ignore
652
- this.getMap().getZoom() > 3
675
+ map.getZoom() > 3
653
676
  ? new google.maps.LatLngBounds(
654
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
655
- // @ts-ignore
656
- this.getMap()
657
- .getBounds()
658
- .getSouthWest(),
659
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
660
- // @ts-ignore
661
- this.getMap()
662
- .getBounds()
663
- .getNorthEast()
677
+ bounds?.getSouthWest(),
678
+ bounds?.getNorthEast()
664
679
  )
665
680
  : new google.maps.LatLngBounds(
666
681
  new google.maps.LatLng(85.02070771743472, -178.48388434375),
667
682
  new google.maps.LatLng(-85.08136444384544, 178.00048865625)
668
683
  )
669
684
 
670
- const bounds = this.getExtendedBounds(mapBounds)
685
+ const extendedMapBounds = this.getExtendedBounds(mapBounds)
671
686
 
672
687
  const iLast = Math.min(iFirst + this.batchSize, this.markers.length)
673
688
 
674
689
  for (let i = iFirst; i < iLast; i++) {
675
690
  const marker = this.markers[i]
676
691
 
677
- if (!marker.isAdded && this.isMarkerInBounds(marker, bounds) && (!this.ignoreHidden || (this.ignoreHidden && marker.getVisible()))) {
692
+ if (!marker.isAdded && this.isMarkerInBounds(marker, extendedMapBounds) && (!this.ignoreHidden || (this.ignoreHidden && marker.getVisible()))) {
678
693
  this.addToClosestCluster(marker)
679
694
  }
680
695
  }
@@ -704,18 +719,13 @@ export class Clusterer {
704
719
  }
705
720
  }
706
721
 
707
- extend(obj1: any, obj2: any): any {
708
- return function applyExtend(object: any) {
709
- // eslint-disable-next-line guard-for-in
722
+ extend<A extends typeof ClusterIcon | typeof Clusterer>(obj1: A, obj2: typeof google.maps.OverlayView) {
723
+ return function applyExtend(this: A, object: typeof google.maps.OverlayView) {
710
724
  for (const property in object.prototype) {
711
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
712
- // @ts-ignore
713
- this.prototype[property] = object.prototype[property]
725
+ this.prototype.set(property, object.prototype.get(property))
714
726
  }
715
727
 
716
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
717
- // @ts-ignore
718
728
  return this
719
- }.apply(obj1, [obj2])
729
+ }.apply<A, [typeof google.maps.OverlayView], any>(obj1, [obj2])
720
730
  }
721
731
  }