Skip to content

Commit 756b846

Browse files
committed
separate useEffect for layer creation and coordinate change to avoid flickering
1 parent 7b7d1cc commit 756b846

File tree

1 file changed

+44
-28
lines changed

1 file changed

+44
-28
lines changed

src/layers/UseCurrentLocationLayer.tsx

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Feature, Map } from 'ol'
2-
import { useEffect } from 'react'
2+
import {useEffect, useRef} from 'react'
33
import VectorLayer from 'ol/layer/Vector'
44
import VectorSource from 'ol/source/Vector'
55
import { Circle, Circle as CircleGeom, Point } from 'ol/geom'
@@ -10,43 +10,59 @@ import { fromLonLat } from 'ol/proj'
1010
const LOCATION_LAYER_KEY = 'gh:current_location'
1111

1212
export default function useCurrentLocationLayer(map: Map, locationState: CurrentLocationStoreState) {
13+
const layerRef = useRef<VectorLayer<VectorSource> | null>(null)
14+
const positionFeatureRef = useRef<Feature | null>(null)
15+
const accuracyFeatureRef = useRef<Feature | null>(null)
16+
17+
// Create layer once when enabled
1318
useEffect(() => {
1419
if (!locationState.enabled) {
15-
removeCurrentLocationLayer(map)
20+
if (layerRef.current) {
21+
map.removeLayer(layerRef.current)
22+
layerRef.current = null
23+
positionFeatureRef.current = null
24+
accuracyFeatureRef.current = null
25+
}
1626
return
17-
}
27+
} else if (!layerRef.current) {
28+
const layer = createLocationLayer()
29+
const positionFeature = new Feature()
30+
const accuracyFeature = new Feature()
31+
layer.getSource()?.addFeature(positionFeature)
32+
layer.getSource()?.addFeature(accuracyFeature)
33+
map.addLayer(layer)
1834

19-
const positionFeature = new Feature()
20-
const accuracyFeature = new Feature()
21-
if (locationState.coordinate) {
22-
const coord = fromLonLat([locationState.coordinate.lng, locationState.coordinate.lat])
23-
positionFeature.setGeometry(new Point(coord))
24-
accuracyFeature.setGeometry(new Circle(coord, locationState.accuracy))
35+
layerRef.current = layer
36+
positionFeatureRef.current = positionFeature
37+
accuracyFeatureRef.current = accuracyFeature
38+
}
2539

26-
if (locationState.syncView) {
27-
// TODO same code as for MoveMapToPoint action, but calling Dispatcher here is ugly
28-
let zoom = map.getView().getZoom()
29-
if (zoom == undefined || zoom < 8) zoom = 8
30-
map.getView().animate({ zoom: zoom, center: coord, duration: 400 })
40+
return () => {
41+
if (layerRef.current) {
42+
map.removeLayer(layerRef.current)
43+
layerRef.current = null
44+
positionFeatureRef.current = null
45+
accuracyFeatureRef.current = null
3146
}
3247
}
48+
}, [locationState.enabled])
3349

34-
const layer = createLocationLayer()
35-
layer.getSource()?.addFeature(positionFeature)
36-
layer.getSource()?.addFeature(accuracyFeature)
37-
map.addLayer(layer)
38-
39-
return () => {
40-
map.removeLayer(layer)
50+
useEffect(() => {
51+
if (!locationState.enabled || !locationState.coordinate || !positionFeatureRef.current || !accuracyFeatureRef.current) {
52+
return
4153
}
42-
}, [locationState.enabled, locationState.coordinate, locationState.syncView])
43-
}
4454

45-
function removeCurrentLocationLayer(map: Map) {
46-
map.getLayers()
47-
.getArray()
48-
.filter(l => l.get(LOCATION_LAYER_KEY))
49-
.forEach(l => map.removeLayer(l))
55+
const coord = fromLonLat([locationState.coordinate.lng, locationState.coordinate.lat])
56+
positionFeatureRef.current.setGeometry(new Point(coord))
57+
accuracyFeatureRef.current.setGeometry(new Circle(coord, locationState.accuracy))
58+
59+
if (locationState.syncView) {
60+
// TODO same code as for MoveMapToPoint action, but calling Dispatcher here is ugly
61+
let zoom = map.getView().getZoom()
62+
if (zoom == undefined || zoom < 8) zoom = 8
63+
map.getView().animate({ zoom: zoom, center: coord, duration: 400 })
64+
}
65+
}, [locationState.coordinate, locationState.accuracy, locationState.syncView, locationState.enabled])
5066
}
5167

5268
function createLocationLayer(): VectorLayer<VectorSource> {

0 commit comments

Comments
 (0)