1- import React , {
2- useState ,
3- useMemo ,
4- useEffect ,
5- useCallback ,
6- useImperativeHandle ,
7- forwardRef ,
8- } from 'react' ;
9- import { isFunction , uuid } from '@rcuse/core' ;
10- import { LngLatBounds } from 'mapbox-gl' ;
11- import Supercluster from 'supercluster' ;
12- import { debounce } from 'lodash-es' ;
13- import bbox from '@turf/bbox' ;
14- import { featureCollection } from '@turf/helpers' ;
15- import { defaultSuperclusterOptions } from './config' ;
16- import { Marker } from '../Marker' ;
17- import { useMap } from '../../hooks/useMap' ;
18-
19- import type { MarkerClusterProps , AnyObject , RefMarkerCluster , Feature , LngLatLike } from './types' ;
20-
21- const InternalMarkerCluster = < D extends AnyObject = AnyObject > (
22- props : MarkerClusterProps < D > ,
23- ref : React . Ref < Supercluster > ,
24- ) => {
1+ import React , { forwardRef , useCallback , useEffect , useImperativeHandle , useMemo , useState } from 'react'
2+ import { debounce , isFunction , uuid } from '@rcuse/core'
3+ import { LngLatBounds } from 'mapbox-gl'
4+ import Supercluster from 'supercluster'
5+ import bbox from '@turf/bbox'
6+ import { featureCollection } from '@turf/helpers'
7+ import { Marker } from '../Marker'
8+ import { useMap } from '../../hooks/useMap'
9+ import { defaultSuperclusterOptions } from './config'
10+
11+ import type { AnyObject , Feature , LngLatLike , MarkerClusterProps , RefMarkerCluster } from './types'
12+
13+ function InternalMarkerCluster < D extends AnyObject = AnyObject > ( props : MarkerClusterProps < D > , ref : React . Ref < Supercluster > ) {
2514 const {
2615 cluster,
2716 render,
@@ -31,120 +20,120 @@ const InternalMarkerCluster = <D extends AnyObject = AnyObject>(
3120 zoomOnClickPadding = 20 ,
3221 onClick,
3322 onClusterClick,
34- } = props ;
35- const { map } = useMap ( ) ;
36- const [ list , setList ] = useState < Feature < D > [ ] > ( [ ] ) ;
23+ } = props
24+ const { map } = useMap ( )
25+ const [ list , setList ] = useState < Feature < D > [ ] > ( [ ] )
3726
3827 const supercluster = useMemo ( ( ) => {
3928 return new Supercluster ( {
4029 ...defaultSuperclusterOptions ,
4130 ...cluster ,
42- } ) ;
43- } , [ ] ) ;
31+ } )
32+ } , [ ] )
4433
45- useEffect ( ( ) => {
46- if ( map ) {
47- map . on ( 'zoom' , handleChangeBoundary ) ;
48- map . on ( 'move' , handleChangeBoundary ) ;
49- map . on ( 'resize' , handleChangeBoundary ) ;
50-
51- return ( ) => {
52- map . off ( 'zoom' , handleChangeBoundary ) ;
53- map . off ( 'move' , handleChangeBoundary ) ;
54- map . off ( 'resize' , handleChangeBoundary ) ;
55- } ;
56- }
57-
58- return undefined ;
59- } , [ map ] ) ;
60-
61- useEffect ( ( ) => {
62- if ( data ) {
63- supercluster . load ( data ) ;
64- handleChangeBoundary ( ) ;
65- }
66- } , [ data ] ) ;
34+ const getMapBoundary = ( ) : [ [ number , number , number , number ] , number ] => {
35+ const bounds = map . getBounds ( )
36+ const zoom = map . getZoom ( )
6737
68- useImperativeHandle ( ref , ( ) => supercluster , [ ] ) ;
38+ return [
39+ [ bounds . getWest ( ) , bounds . getSouth ( ) , bounds . getEast ( ) , bounds . getNorth ( ) ] ,
40+ Math . round ( zoom ) ,
41+ ]
42+ }
6943
7044 const handleChangeBoundary = useCallback (
71- debounce ( ( ) => {
72- const mapBoundary = getMapBoundary ( ) ;
45+ debounce ( { delay : 500 } , ( ) => {
46+ const mapBoundary = getMapBoundary ( )
7347
74- const result = supercluster . getClusters ( ...mapBoundary ) ;
48+ const result = supercluster . getClusters ( ...mapBoundary )
7549
7650 setList (
7751 result . map ( ( item ) => {
7852 return {
7953 ...item ,
8054 id : item . id || uuid ( ) ,
81- } ;
55+ }
8256 } ) ,
83- ) ;
84- } , 500 ) ,
57+ )
58+ } ) ,
8559 [ ] ,
86- ) ;
60+ )
8761
88- const getMapBoundary = ( ) : [ [ number , number , number , number ] , number ] => {
89- const bounds = map . getBounds ( ) ;
90- const zoom = map . getZoom ( ) ;
62+ useEffect ( ( ) => {
63+ if ( map ) {
64+ map . on ( 'zoom' , handleChangeBoundary )
65+ map . on ( 'move' , handleChangeBoundary )
66+ map . on ( 'resize' , handleChangeBoundary )
9167
92- return [
93- [ bounds . getWest ( ) , bounds . getSouth ( ) , bounds . getEast ( ) , bounds . getNorth ( ) ] ,
94- Math . round ( zoom ) ,
95- ] ;
96- } ;
68+ return ( ) => {
69+ map . off ( 'zoom' , handleChangeBoundary )
70+ map . off ( 'move' , handleChangeBoundary )
71+ map . off ( 'resize' , handleChangeBoundary )
72+ }
73+ }
74+
75+ return undefined
76+ } , [ map ] )
77+
78+ useEffect ( ( ) => {
79+ if ( data ) {
80+ supercluster . load ( data )
81+ handleChangeBoundary ( )
82+ }
83+ } , [ data ] )
84+
85+ useImperativeHandle ( ref , ( ) => supercluster , [ ] )
9786
9887 const handleClusterMarkerClick = ( data : any ) => {
99- const { properties } = data ;
88+ const { properties } = data
10089
101- if ( ! properties ?. cluster ) return ;
90+ if ( ! properties ?. cluster )
91+ return
10292
103- const children = supercluster . getLeaves ( properties . cluster_id , Infinity ) ;
104- const childrenBbox = bbox ( featureCollection ( children ) ) as [ number , number , number , number ] ;
93+ const children = supercluster . getLeaves ( properties . cluster_id , Number . POSITIVE_INFINITY )
94+ const childrenBbox = bbox ( featureCollection ( children ) ) as [ number , number , number , number ]
10595
10696 map . fitBounds ( LngLatBounds . convert ( childrenBbox ) , {
10797 padding : zoomOnClickPadding ,
108- } ) ;
109- } ;
98+ } )
99+ }
110100
111101 return (
112102 < >
113103 { list . map ( ( item ) => {
114- const { geometry, properties } = item ;
115- const { point_count, cluster, cluster_id } = properties ;
104+ const { geometry, properties } = item
105+ const { point_count, cluster, cluster_id } = properties
116106
117107 if ( cluster ) {
118108 return (
119109 < Marker
120110 key = { item . id }
121111 lngLat = { geometry . coordinates as LngLatLike }
122112 onClick = { ( ) => {
123- onClusterClick ?.( point_count , cluster_id ) ;
124- if ( zoomOnClick ) {
125- handleClusterMarkerClick ( item ) ;
126- }
113+ onClusterClick ?.( point_count , cluster_id )
114+ if ( zoomOnClick )
115+ handleClusterMarkerClick ( item )
127116 } }
128117 >
129118 { isFunction ( renderCluster ) ? renderCluster ( point_count , cluster_id ) : renderCluster }
130119 </ Marker >
131- ) ;
120+ )
132121 }
133122
134123 return (
135124 < Marker
136125 key = { item . id }
137126 lngLat = { geometry . coordinates as LngLatLike }
138127 onClick = { ( ) => {
139- onClick ?.( item ) ;
128+ onClick ?.( item )
140129 } }
141130 >
142131 { isFunction ( render ) ? render ( item ) : render }
143132 </ Marker >
144- ) ;
133+ )
145134 } ) }
146135 </ >
147- ) ;
148- } ;
136+ )
137+ }
149138
150- export const MarkerCluster = forwardRef ( InternalMarkerCluster ) as RefMarkerCluster ;
139+ export const MarkerCluster = forwardRef ( InternalMarkerCluster ) as RefMarkerCluster
0 commit comments