Skip to content

Commit 3c21225

Browse files
committed
Adding Spiderfier support
1 parent f5da494 commit 3c21225

File tree

5 files changed

+109
-22
lines changed

5 files changed

+109
-22
lines changed

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ This repo is proudly sponsored by:
1313

1414
## Demo
1515

16-
![Demo](https://raw.githubusercontent.com/venits/react-native-map-clustering/master/assets/demo.gif)
16+
![Demo](https://raw.githubusercontent.com/venits/react-native-map-clustering/assets/assets/demo.gif)
17+
18+
## Spiral
19+
20+
### Converting same locations in spiral view (done automatically)
21+
22+
![Spiral](https://raw.githubusercontent.com/venits/react-native-map-clustering/assets/assets/spider_lib.png)
1723

1824
## Installation
1925

@@ -43,14 +49,19 @@ const INITIAL_REGION = {
4349

4450
const App = () => (
4551
<MapView initialRegion={INITIAL_REGION} style={{ flex: 1 }}>
46-
<Marker coordinate={{ latitude: 52.0, longitude: 18.2 }} />
4752
<Marker coordinate={{ latitude: 52.4, longitude: 18.7 }} />
4853
<Marker coordinate={{ latitude: 52.1, longitude: 18.4 }} />
4954
<Marker coordinate={{ latitude: 52.6, longitude: 18.3 }} />
5055
<Marker coordinate={{ latitude: 51.6, longitude: 18.0 }} />
5156
<Marker coordinate={{ latitude: 53.1, longitude: 18.8 }} />
5257
<Marker coordinate={{ latitude: 52.9, longitude: 19.4 }} />
5358
<Marker coordinate={{ latitude: 52.2, longitude: 21 }} />
59+
<Marker coordinate={{ latitude: 52.4, longitude: 21 }} />
60+
<Marker coordinate={{ latitude: 51.8, longitude: 20 }} />
61+
<Marker coordinate={{ latitude: 51.8, longitude: 20 }} />
62+
<Marker coordinate={{ latitude: 51.8, longitude: 20 }} />
63+
<Marker coordinate={{ latitude: 51.8, longitude: 20 }} />
64+
<Marker coordinate={{ latitude: 51.8, longitude: 20 }} />
5465
</MapView>
5566
);
5667

assets/demo.gif

-2.54 MB
Binary file not shown.

lib/ClusteredMapView.js

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import React, { memo, useState, useEffect, useMemo, createRef } from "react";
22
import { Dimensions, LayoutAnimation, Platform } from "react-native";
3-
import MapView from "react-native-maps";
3+
import MapView, { Marker, Polyline } from "react-native-maps";
44
import SuperCluster from "supercluster";
55
import ClusterMarker from "./ClusteredMarker";
66
import {
77
isMarker,
88
markerToGeoJSONFeature,
99
calculateBBox,
10-
returnMapZoom
10+
returnMapZoom,
11+
generateSpiral
1112
} from "./helpers";
1213

1314
const ClusteredMapView = ({
@@ -23,17 +24,23 @@ const ClusteredMapView = ({
2324
clusteringEnabled,
2425
clusterColor,
2526
clusterTextColor,
27+
spiderLineColor,
2628
layoutAnimationConf,
2729
animationEnabled,
2830
renderCluster,
2931
...restProps
3032
}) => {
3133
const [markers, updateMarkers] = useState([]);
34+
const [spiderMarkers, updateSpiderMarker] = useState([]);
3235
const [otherChildren, updateChildren] = useState([]);
3336
const [superCluster, setSuperCluster] = useState(null);
3437
const [currentRegion, updateRegion] = useState(
3538
restProps.region || restProps.initialRegion
3639
);
40+
41+
const [isSpiderfier, updateSpiderfier] = useState(false);
42+
const [spiderfierMarker, updateSpiderfierMarker] = useState(null);
43+
const [clusterChildren, updateClusterChildren] = useState(null);
3744
const mapRef = createRef();
3845

3946
const propsChildren = useMemo(() => React.Children.toArray(children), [
@@ -76,6 +83,23 @@ const ClusteredMapView = ({
7683
setSuperCluster(superCluster);
7784
}, [children, restProps.region, restProps.initialRegion]);
7885

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+
79103
const _onRegionChangeComplete = region => {
80104
if (superCluster) {
81105
const bBox = calculateBBox(region);
@@ -86,14 +110,21 @@ const ClusteredMapView = ({
86110
LayoutAnimation.configureNext(layoutAnimationConf);
87111
}
88112

113+
if (zoom >= 17 && markers.length === 1 && clusterChildren) {
114+
updateSpiderfier(true);
115+
} else {
116+
updateSpiderfier(false);
117+
}
118+
89119
updateMarkers(markers);
90120
onRegionChangeComplete(region, markers);
91121
updateRegion(region);
92122
}
93123
};
94124

95125
const _onClusterPress = cluster => () => {
96-
const children = superCluster.getLeaves(cluster.id);
126+
const children = superCluster.getLeaves(cluster.id, (limit = Infinity));
127+
updateClusterChildren(children);
97128

98129
if (preserveClusterPressBehavior) {
99130
onClusterPress(cluster, children);
@@ -124,24 +155,48 @@ const ClusteredMapView = ({
124155
{markers.map(marker =>
125156
marker.properties.point_count === 0 ? (
126157
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
143176
)}
144177
{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+
})}
145200
</MapView>
146201
);
147202
};
@@ -162,6 +217,7 @@ ClusteredMapView.defaultProps = {
162217
// Cluster styles
163218
clusterColor: "#00B386",
164219
clusterTextColor: "#FFFFFF",
220+
spiderLineColor: "#FF0000",
165221
// Callbacks
166222
onRegionChangeComplete: () => {},
167223
onClusterPress: () => {},

lib/helpers.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@ export const markerToGeoJSONFeature = (marker, index) => {
4949
};
5050
};
5151

52+
export const generateSpiral = (count, centerLocation, clusterChildren) => {
53+
let res = [];
54+
res.length = count;
55+
let angle = 0;
56+
57+
for (let i = 0; i < count; i++) {
58+
angle = 0.25 * (i * 0.5);
59+
let latitude = centerLocation[1] + 0.0002 * angle * Math.cos(angle);
60+
let longitude = centerLocation[0] + 0.0002 * angle * Math.sin(angle);
61+
res[i] = {
62+
longitude,
63+
latitude,
64+
image: clusterChildren[i] && clusterChildren[i].properties.image,
65+
onPress: clusterChildren[i] && clusterChildren[i].properties.onPress
66+
};
67+
}
68+
69+
return res;
70+
};
71+
5272
export const returnMarkerStyle = points => {
5373
if (points >= 50) {
5474
return {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-map-clustering",
3-
"version": "3.0.6",
3+
"version": "3.1.2",
44
"description": "Map clustering both for Android and iOS",
55
"main": "index.js",
66
"scripts": {

0 commit comments

Comments
 (0)