-
Notifications
You must be signed in to change notification settings - Fork 82
/
GMap.js
131 lines (126 loc) · 3.26 KB
/
GMap.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import React from 'react';
import compose from 'recompose/compose';
import defaultProps from 'recompose/defaultProps';
import withState from 'recompose/withState';
import withHandlers from 'recompose/withHandlers';
import withPropsOnChange from 'recompose/withPropsOnChange';
import GoogleMapReact from 'google-map-react';
import ClusterMarker from './markers/ClusterMarker';
import SimpleMarker from './markers/SimpleMarker';
import supercluster from 'points-cluster';
import { susolvkaCoords, markersData } from './data/fakeData';
export const gMap = ({
style, hoverDistance, options,
mapProps: { center, zoom },
onChange, onChildMouseEnter, onChildMouseLeave,
clusters,
}) => (
<GoogleMapReact
style={style}
options={options}
hoverDistance={hoverDistance}
center={center}
zoom={zoom}
onChange={onChange}
onChildMouseEnter={onChildMouseEnter}
onChildMouseLeave={onChildMouseLeave}
>
{
clusters
.map(({ ...markerProps, id, numPoints }) => (
numPoints === 1
? <SimpleMarker key={id} {...markerProps} />
: <ClusterMarker key={id} {...markerProps} />
))
}
</GoogleMapReact>
);
export const gMapHOC = compose(
defaultProps({
clusterRadius: 60,
hoverDistance: 30,
options: {
minZoom: 3,
maxZoom: 15,
},
style: {
position: 'relative',
margin: 0,
padding: 0,
flex: 1,
},
}),
// withState so you could change markers if you want
withState(
'markers',
'setMarkers',
markersData
),
withState(
'hoveredMarkerId',
'setHoveredMarkerId',
-1
),
withState(
'mapProps',
'setMapProps',
{
center: susolvkaCoords,
zoom: 10,
}
),
// describe events
withHandlers({
onChange: ({ setMapProps }) => ({ center, zoom, bounds }) => {
setMapProps({ center, zoom, bounds });
},
onChildMouseEnter: ({ setHoveredMarkerId }) => (hoverKey, { id }) => {
setHoveredMarkerId(id);
},
onChildMouseLeave: ({ setHoveredMarkerId }) => (/* hoverKey, childProps */) => {
setHoveredMarkerId(-1);
},
}),
// precalculate clusters if markers data has changed
withPropsOnChange(
['markers'],
({ markers = [], clusterRadius, options: { minZoom, maxZoom } }) => ({
getCluster: supercluster(
markers,
{
minZoom, // min zoom to generate clusters on
maxZoom, // max zoom level to cluster the points on
radius: clusterRadius, // cluster radius in pixels
}
),
})
),
// get clusters specific for current bounds and zoom
withPropsOnChange(
['mapProps', 'getCluster'],
({ mapProps, getCluster }) => ({
clusters: mapProps.bounds
? getCluster(mapProps)
.map(({ wx, wy, numPoints, points }) => ({
lat: wy,
lng: wx,
text: numPoints,
numPoints,
id: `${numPoints}_${points[0].id}`,
}))
: [],
})
),
// set hovered
withPropsOnChange(
['clusters', 'hoveredMarkerId'],
({ clusters, hoveredMarkerId }) => ({
clusters: clusters
.map(({ ...cluster, id }) => ({
...cluster,
hovered: id === hoveredMarkerId,
})),
})
),
);
export default gMapHOC(gMap);