1
1
import React , { memo , useState , useEffect , useMemo , createRef } from "react" ;
2
2
import { Dimensions , LayoutAnimation , Platform } from "react-native" ;
3
- import MapView from "react-native-maps" ;
3
+ import MapView , { Marker , Polyline } from "react-native-maps" ;
4
4
import SuperCluster from "supercluster" ;
5
5
import ClusterMarker from "./ClusteredMarker" ;
6
6
import {
7
7
isMarker ,
8
8
markerToGeoJSONFeature ,
9
9
calculateBBox ,
10
- returnMapZoom
10
+ returnMapZoom ,
11
+ generateSpiral
11
12
} from "./helpers" ;
12
13
13
14
const ClusteredMapView = ( {
@@ -23,17 +24,23 @@ const ClusteredMapView = ({
23
24
clusteringEnabled,
24
25
clusterColor,
25
26
clusterTextColor,
27
+ spiderLineColor,
26
28
layoutAnimationConf,
27
29
animationEnabled,
28
30
renderCluster,
29
31
...restProps
30
32
} ) => {
31
33
const [ markers , updateMarkers ] = useState ( [ ] ) ;
34
+ const [ spiderMarkers , updateSpiderMarker ] = useState ( [ ] ) ;
32
35
const [ otherChildren , updateChildren ] = useState ( [ ] ) ;
33
36
const [ superCluster , setSuperCluster ] = useState ( null ) ;
34
37
const [ currentRegion , updateRegion ] = useState (
35
38
restProps . region || restProps . initialRegion
36
39
) ;
40
+
41
+ const [ isSpiderfier , updateSpiderfier ] = useState ( false ) ;
42
+ const [ spiderfierMarker , updateSpiderfierMarker ] = useState ( null ) ;
43
+ const [ clusterChildren , updateClusterChildren ] = useState ( null ) ;
37
44
const mapRef = createRef ( ) ;
38
45
39
46
const propsChildren = useMemo ( ( ) => React . Children . toArray ( children ) , [
@@ -76,6 +83,23 @@ const ClusteredMapView = ({
76
83
setSuperCluster ( superCluster ) ;
77
84
} , [ children , restProps . region , restProps . initialRegion ] ) ;
78
85
86
+ useEffect ( ( ) => {
87
+ if ( isSpiderfier && markers . length > 0 ) {
88
+ let positions = generateSpiral (
89
+ markers [ 0 ] . properties . point_count ,
90
+ markers [ 0 ] . geometry . coordinates ,
91
+ clusterChildren
92
+ ) ;
93
+ updateSpiderMarker ( positions ) ;
94
+ updateSpiderfierMarker ( {
95
+ latitude : markers [ 0 ] . geometry . coordinates [ 1 ] ,
96
+ longitude : markers [ 0 ] . geometry . coordinates [ 0 ]
97
+ } ) ;
98
+ } else {
99
+ updateSpiderMarker ( [ ] ) ;
100
+ }
101
+ } , [ isSpiderfier ] ) ;
102
+
79
103
const _onRegionChangeComplete = region => {
80
104
if ( superCluster ) {
81
105
const bBox = calculateBBox ( region ) ;
@@ -86,14 +110,21 @@ const ClusteredMapView = ({
86
110
LayoutAnimation . configureNext ( layoutAnimationConf ) ;
87
111
}
88
112
113
+ if ( zoom >= 17 && markers . length === 1 && clusterChildren ) {
114
+ updateSpiderfier ( true ) ;
115
+ } else {
116
+ updateSpiderfier ( false ) ;
117
+ }
118
+
89
119
updateMarkers ( markers ) ;
90
120
onRegionChangeComplete ( region , markers ) ;
91
121
updateRegion ( region ) ;
92
122
}
93
123
} ;
94
124
95
125
const _onClusterPress = cluster => ( ) => {
96
- const children = superCluster . getLeaves ( cluster . id ) ;
126
+ const children = superCluster . getLeaves ( cluster . id , ( limit = Infinity ) ) ;
127
+ updateClusterChildren ( children ) ;
97
128
98
129
if ( preserveClusterPressBehavior ) {
99
130
onClusterPress ( cluster , children ) ;
@@ -124,24 +155,48 @@ const ClusteredMapView = ({
124
155
{ markers . map ( marker =>
125
156
marker . properties . point_count === 0 ? (
126
157
propsChildren [ marker . properties . index ]
127
- ) : renderCluster ? (
128
- renderCluster ( {
129
- onPress : _onClusterPress ( marker ) ,
130
- clusterColor,
131
- clusterTextColor,
132
- ...marker
133
- } )
134
- ) : (
135
- < ClusterMarker
136
- key = { `cluster-${ marker . id } ` }
137
- { ...marker }
138
- onPress = { _onClusterPress ( marker ) }
139
- clusterColor = { clusterColor }
140
- clusterTextColor = { clusterTextColor }
141
- />
142
- )
158
+ ) : ! isSpiderfier ? (
159
+ renderCluster ? (
160
+ renderCluster ( {
161
+ onPress : _onClusterPress ( marker ) ,
162
+ clusterColor,
163
+ clusterTextColor,
164
+ ...marker
165
+ } )
166
+ ) : (
167
+ < ClusterMarker
168
+ key = { `cluster-${ marker . id } ` }
169
+ { ...marker }
170
+ onPress = { _onClusterPress ( marker ) }
171
+ clusterColor = { clusterColor }
172
+ clusterTextColor = { clusterTextColor }
173
+ />
174
+ )
175
+ ) : null
143
176
) }
144
177
{ otherChildren }
178
+ { spiderMarkers . map ( marker => (
179
+ < Marker
180
+ key = { marker . latitude }
181
+ coordinate = { marker }
182
+ image = { marker . image }
183
+ onPress = { marker . onPress }
184
+ > </ Marker >
185
+ ) ) }
186
+ { spiderMarkers . map ( ( marker , index ) => {
187
+ {
188
+ return (
189
+ spiderfierMarker && (
190
+ < Polyline
191
+ key = { index }
192
+ coordinates = { [ spiderfierMarker , marker , spiderfierMarker ] }
193
+ strokeColor = { spiderLineColor }
194
+ strokeWidth = { 1 }
195
+ />
196
+ )
197
+ ) ;
198
+ }
199
+ } ) }
145
200
</ MapView >
146
201
) ;
147
202
} ;
@@ -162,6 +217,7 @@ ClusteredMapView.defaultProps = {
162
217
// Cluster styles
163
218
clusterColor : "#00B386" ,
164
219
clusterTextColor : "#FFFFFF" ,
220
+ spiderLineColor : "#FF0000" ,
165
221
// Callbacks
166
222
onRegionChangeComplete : ( ) => { } ,
167
223
onClusterPress : ( ) => { } ,
0 commit comments