-
Notifications
You must be signed in to change notification settings - Fork 62
Expand file tree
/
Copy pathUseQueryPointsLayer.tsx
More file actions
118 lines (112 loc) · 4.08 KB
/
UseQueryPointsLayer.tsx
File metadata and controls
118 lines (112 loc) · 4.08 KB
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
import { Feature, Map } from 'ol'
import { QueryPoint, QueryPointType } from '@/stores/QueryStore'
import { useEffect } from 'react'
import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'
import { Geometry, Point } from 'ol/geom'
import { fromLonLat, toLonLat } from 'ol/proj'
import { Modify } from 'ol/interaction'
import Dispatcher from '@/stores/Dispatcher'
import { SetPoint } from '@/actions/Actions'
import { coordinateToText } from '@/Converters'
import { Icon, Style } from 'ol/style'
import { createSvg } from '@/layers/createMarkerSVG'
const MARKER_SIZE = 35
export default function useQueryPointsLayer(map: Map, queryPoints: QueryPoint[]) {
useEffect(() => {
removeQueryPoints(map)
const queryPointsLayer = addQueryPointsLayer(map, queryPoints)
removeDragInteractions(map)
addDragInteractions(map, queryPointsLayer)
return () => {
removeQueryPoints(map)
removeDragInteractions(map)
}
}, [map, queryPoints])
}
function removeQueryPoints(map: Map) {
map.getLayers()
.getArray()
.filter(l => l.get('gh:query_points'))
.forEach(l => map.removeLayer(l))
}
function addQueryPointsLayer(map: Map, queryPoints: QueryPoint[]) {
const features: Feature<Geometry>[] = queryPoints
.map((point, i) => {
return { index: i, point: point }
})
.filter(indexPoint => indexPoint.point.isInitialized)
.map((indexPoint, i) => {
const feature = new Feature({
geometry: new Point(fromLonLat([indexPoint.point.coordinate.lng, indexPoint.point.coordinate.lat])),
})
feature.set('gh:query_point', indexPoint.point)
feature.set('gh:marker_props', {
color: indexPoint.point.color,
number: indexPoint.point.type == QueryPointType.Via ? i : undefined,
size: MARKER_SIZE,
})
return feature
})
const queryPointsLayer = new VectorLayer({
source: new VectorSource({
features: features,
}),
})
queryPointsLayer.set('gh:query_points', true)
queryPointsLayer.setZIndex(3)
const cachedStyles: { [id: string]: Style } = {}
queryPointsLayer.setStyle(feature => {
const props = feature.get('gh:marker_props')
const key = props.number + '-' + props.color + '-' + props.size
let style = cachedStyles[key]
if (style) return style
style = new Style({
image: new Icon({
src: 'data:image/svg+xml;utf8,' + createSvg(props),
displacement: [0, MARKER_SIZE / 2],
}),
})
cachedStyles[key] = style
return style
})
map.addLayer(queryPointsLayer)
return queryPointsLayer
}
function removeDragInteractions(map: Map) {
map.getInteractions()
.getArray()
.filter(l => l.get('gh:drag_query_point'))
.forEach(i => map.removeInteraction(i))
}
function addDragInteractions(map: Map, queryPointsLayer: VectorLayer<VectorSource>) {
let tmp = queryPointsLayer.getSource()
if (tmp == null) throw new Error('source must not be null') // typescript requires this
const modify = new Modify({
hitDetection: queryPointsLayer,
source: tmp,
style: [],
})
modify.on('modifystart', e => {
map.getViewport().style.cursor = 'grabbing'
})
modify.on('modifyend', e => {
map.getViewport().style.cursor = 'default'
const feature = (e as any).features.getArray()[0]
const point = feature.get('gh:query_point')
const coordinateLonLat = toLonLat(feature.getGeometry().getCoordinates())
const coordinate = { lng: coordinateLonLat[0], lat: coordinateLonLat[1] }
Dispatcher.dispatch(
new SetPoint(
{
...point,
coordinate,
queryText: coordinateToText(coordinate),
},
false
)
)
})
modify.set('gh:drag_query_point', true)
map.addInteraction(modify)
}