11import { Feature , Map } from 'ol'
2- import { useEffect } from 'react'
2+ import { useEffect , useRef } from 'react'
33import VectorLayer from 'ol/layer/Vector'
44import VectorSource from 'ol/source/Vector'
55import { Circle , Circle as CircleGeom , Point } from 'ol/geom'
@@ -10,43 +10,59 @@ import { fromLonLat } from 'ol/proj'
1010const LOCATION_LAYER_KEY = 'gh:current_location'
1111
1212export 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
5268function createLocationLayer ( ) : VectorLayer < VectorSource > {
0 commit comments