@react-google-maps/marker-clusterer 2.10.0 → 2.11.1

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 = []
@@ -134,56 +137,55 @@ export class Clusterer {
134
137
  this.setupStyles()
135
138
 
136
139
  this.addMarkers(optMarkers, true)
137
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
138
- // @ts-ignore
140
+
139
141
  this.setMap(map) // Note: this causes onAdd to be called
140
142
  }
141
143
 
144
+ onZoomChanged() {
145
+ this.resetViewport(false)
146
+
147
+ // Workaround for this Google bug: when map is at level 0 and "-" of
148
+ // zoom slider is clicked, a "zoom_changed" event is fired even though
149
+ // the map doesn't zoom out any further. In this situation, no "idle"
150
+ // event is triggered so the cluster markers that have been removed
151
+ // do not get redrawn. Same goes for a zoom in at maxZoom.
152
+ if (
153
+ this.getMap()?.getZoom() === (this.get('minZoom') || 0) ||
154
+
155
+ this.getMap()?.getZoom() === this.get('maxZoom')
156
+ ) {
157
+ google.maps.event.trigger(this, 'idle')
158
+ }
159
+ }
160
+
161
+ onIdle() {
162
+ this.redraw()
163
+ }
164
+
142
165
  onAdd() {
143
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
144
- // @ts-ignore
145
- this.activeMap = this.getMap()
166
+ const map = this.getMap()
167
+
168
+ this.activeMap = map
146
169
 
147
170
  this.ready = true
148
171
 
149
172
  this.repaint()
150
173
 
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
- ]
174
+ if (map !== null) {
175
+ // Add the map event listeners
176
+ this.listeners = [
177
+ google.maps.event.addListener(
178
+ map,
179
+ 'zoom_changed',
180
+ this.onZoomChanged
181
+ ),
182
+ google.maps.event.addListener(
183
+ map,
184
+ 'idle',
185
+ this.onIdle
186
+ ),
187
+ ]
188
+ }
187
189
  }
188
190
 
189
191
  onRemove() {
@@ -237,14 +239,18 @@ export class Clusterer {
237
239
 
238
240
  for (let i = 0; i < markers.length; i++) {
239
241
  const position = markers[i].getPosition()
242
+
240
243
  if (position) {
241
244
  bounds.extend(position)
242
245
  }
243
246
  }
244
247
 
245
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
246
- // @ts-ignore
247
- this.getMap().fitBounds(bounds)
248
+ const map = this.getMap()
249
+
250
+ if (map !== null && 'fitBounds' in map) {
251
+ map.fitBounds(bounds)
252
+ }
253
+
248
254
  }
249
255
 
250
256
  getGridSize(): number {
@@ -496,36 +502,51 @@ export class Clusterer {
496
502
  }
497
503
 
498
504
  getExtendedBounds(bounds: google.maps.LatLngBounds): google.maps.LatLngBounds {
499
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
500
- // @ts-ignore
501
505
  const projection = this.getProjection()
506
+
502
507
  // Convert the points to pixels and the extend out by the grid size.
503
508
  const trPix = projection.fromLatLngToDivPixel(
504
509
  // Turn the bounds into latlng.
505
510
  new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getNorthEast().lng())
506
511
  )
507
512
 
508
- trPix.x += this.gridSize
509
- trPix.y -= this.gridSize
513
+ if (trPix !== null) {
514
+ trPix.x += this.gridSize
515
+ trPix.y -= this.gridSize
516
+ }
510
517
 
511
518
  const blPix = projection.fromLatLngToDivPixel(
512
519
  // Turn the bounds into latlng.
513
520
  new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng())
514
521
  )
515
522
 
516
- blPix.x -= this.gridSize
517
- blPix.y += this.gridSize
523
+ if (blPix !== null) {
524
+ blPix.x -= this.gridSize
525
+ blPix.y += this.gridSize
526
+ }
527
+
518
528
 
519
529
  // Extend the bounds to contain the new bounds.
520
- bounds.extend(
530
+ if (trPix !== null) {
521
531
  // Convert the pixel points back to LatLng nw
522
- projection.fromDivPixelToLatLng(trPix)
523
- )
532
+ const point1 = projection.fromDivPixelToLatLng(trPix)
533
+
534
+ if (point1 !== null) {
535
+ bounds.extend(point1)
536
+ }
537
+ }
524
538
 
525
- bounds.extend(
539
+ if (blPix !== null) {
526
540
  // Convert the pixel points back to LatLng sw
527
- projection.fromDivPixelToLatLng(blPix)
528
- )
541
+ const point2 = projection.fromDivPixelToLatLng(blPix)
542
+
543
+ if (point2 !== null) {
544
+ bounds.extend(
545
+ point2
546
+ )
547
+ }
548
+ }
549
+
529
550
 
530
551
  return bounds
531
552
  }
@@ -642,39 +663,33 @@ export class Clusterer {
642
663
  }
643
664
  }
644
665
 
666
+ const map = this.getMap()
667
+
668
+ const bounds = map !== null && 'getBounds' in map ? map.getBounds() : null
669
+
670
+ const zoom = map?.getZoom() || 0
645
671
  // Get our current map view bounds.
646
672
  // Create a new bounds object so we don't affect the map.
647
673
  //
648
674
  // See Comments 9 & 11 on Issue 3651 relating to this workaround for a Google Maps bug:
649
- const mapBounds =
650
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
651
- // @ts-ignore
652
- this.getMap().getZoom() > 3
675
+ const mapBounds = zoom > 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
  }