@@ -32,10 +32,11 @@ import {
3232} from '@terrestris/ol-util' ;
3333
3434import useMap from '../useMap/useMap' ;
35+ import useOlListener from '../useOlListener/useOlListener' ;
3536
3637export interface FeatureLayerResult {
3738 feature : OlFeature ;
38- layer : WmsLayer | WmtsLayer | WfsLayer ;
39+ layer : WmsLayer | WmtsLayer | WfsLayer ;
3940 featureType : string ;
4041}
4142
@@ -83,53 +84,69 @@ export const useCoordinateInfo = ({
8384
8485 const map = useMap ( ) ;
8586
86- const [ clickCoordinate , setClickCoordinate ] = useState < OlCoordinate | undefined > ( ) ;
87+ const mapView = useMemo ( ( ) => map ?. getView ( ) , [ map ] ) ;
88+
89+ const [ mapCoordinate , setMapCoordinate ] = useState < OlCoordinate | undefined > ( ) ;
8790 const [ pixelCoordinate , setPixelCoordinate ] = useState < OlPixel | undefined > ( ) ;
8891 const [ featureResults , setFeatureResults ] = useState < FeatureLayerResult [ ] | undefined > ( ) ;
8992 const [ loading , setLoading ] = useState < boolean > ( false ) ;
93+ const [ viewResolution , setViewResolution ] = useState < number | undefined > ( mapView ?. getResolution ( ) ) ;
9094
9195 const abortControllers = useRef < Map < string , AbortController > > ( new Map ( ) ) ;
9296
93- const mapView = useMemo ( ( ) => map ?. getView ( ) , [ map ] ) ;
94- const viewResolution = useMemo ( ( ) => mapView ?. getResolution ( ) , [ mapView ] ) ;
9597 const viewProjection = useMemo ( ( ) => mapView ?. getProjection ( ) , [ mapView ] ) ;
9698
97- const wmsMapLayers = useMemo ( ( ) => {
99+ useOlListener (
100+ mapView ,
101+ v => v . on ( 'change:resolution' , ( ) => {
102+ setViewResolution ( v . getResolution ( ) ) ;
103+ } ) ,
104+ [ mapView ]
105+ ) ;
106+
107+ const wmsMapLayerUids = useMemo ( ( ) => {
98108 if ( _isNil ( map ) || _isNil ( pixelCoordinate ) ) {
99109 return [ ] ;
100110 }
101111 return map . getAllLayers ( )
102112 . reverse ( )
103113 . filter ( layerFilter )
104- . filter ( l => l . getData && l . getData ( pixelCoordinate ) && isWmsLayer ( l ) ) as WmsLayer [ ] ;
114+ . filter ( l => l . getData && l . getData ( pixelCoordinate ) && isWmsLayer ( l ) )
115+ . map ( getUid ) ;
105116 } , [ layerFilter , map , pixelCoordinate ] ) ;
106117
107- const wmtsMapLayers = useMemo ( ( ) => {
118+ const wmtsMapLayerUids = useMemo ( ( ) => {
108119 if ( _isNil ( map ) || _isNil ( pixelCoordinate ) ) {
109120 return [ ] ;
110121 }
111122 return map . getAllLayers ( )
112123 . reverse ( )
113124 . filter ( layerFilter )
114- . filter ( l => isWmtsLayer ( l ) ) as WmtsLayer [ ] ;
125+ . filter ( l => isWmtsLayer ( l ) )
126+ . map ( getUid ) ;
115127 } , [ layerFilter , map , pixelCoordinate ] ) ;
116128
117- const wfsMapLayers = useMemo ( ( ) => {
129+ const wfsMapLayerUids = useMemo ( ( ) => {
118130 if ( _isNil ( map ) || _isNil ( pixelCoordinate ) ) {
119131 return [ ] ;
120132 }
121133 return map . getAllLayers ( )
122134 . reverse ( )
123135 . filter ( layerFilter )
124- . filter ( l => isWfsLayer ( l ) ) as WfsLayer [ ] ;
136+ . filter ( l => isWfsLayer ( l ) )
137+ . map ( getUid ) ;
125138 } , [ layerFilter , map , pixelCoordinate ] ) ;
126139
127- const orderedLayers = useMemo ( ( ) => {
140+ const orderedLayerUids = useMemo ( ( ) => {
128141 if ( _isNil ( map ) ) {
129142 return [ ] ;
130143 }
131144 const all = map . getAllLayers ( ) . reverse ( ) ;
132- const relevantLayers = [ ...wfsMapLayers , ...wmtsMapLayers , ...wmsMapLayers ] ;
145+ const relevantLayers = map . getAllLayers ( )
146+ . filter ( l => {
147+ const uid = getUid ( l ) ;
148+ return wfsMapLayerUids . includes ( uid ) || wmtsMapLayerUids . includes ( uid ) || wmsMapLayerUids . includes ( uid ) ;
149+ } ) ;
133150
134151 relevantLayers . sort ( ( a , b ) => {
135152 if ( _isNil ( a ) || _isNil ( b ) ) {
@@ -142,8 +159,8 @@ export const useCoordinateInfo = ({
142159 return aIndex - bIndex ;
143160 } ) ;
144161
145- return relevantLayers ;
146- } , [ map , wfsMapLayers , wmtsMapLayers , wmsMapLayers ] ) ;
162+ return relevantLayers . map ( getUid ) ;
163+ } , [ map , wfsMapLayerUids , wmtsMapLayerUids , wmsMapLayerUids ] ) ;
147164
148165 /**
149166 * Event handler for pointer move events on the map.
@@ -253,17 +270,21 @@ export const useCoordinateInfo = ({
253270 }
254271
255272 const results : FeatureLayerResult [ ] = [ ] ;
256- const layers = useWms ? wmsMapLayers : wmtsMapLayers ;
273+ const layerUids = useWms ? wmsMapLayerUids : wmtsMapLayerUids ;
257274
258- for ( const layer of layers ) {
275+ for ( const layerId of layerUids ) {
259276 try {
260- const layerId = getUid ( layer ) ;
261277 const abortController = abortControllers . current . get ( layerId ) ;
262278
263279 if ( ! abortController ) {
264280 continue ;
265281 }
266282
283+ const layer = map . getAllLayers ( ) . find ( l => getUid ( l ) === layerId ) as WmsLayer | WmtsLayer | undefined ;
284+ if ( ! layer ) {
285+ continue ;
286+ }
287+
267288 const layerSource = layer . getSource ( ) ;
268289 if ( ! layerSource ) {
269290 continue ;
@@ -305,7 +326,7 @@ export const useCoordinateInfo = ({
305326 if ( fetchOpts instanceof Function ) {
306327 opts = fetchOpts ( layer ) ;
307328 } else {
308- opts = fetchOpts [ getUid ( layer ) ] ;
329+ opts = fetchOpts [ layerId ] ;
309330 }
310331
311332 const response = await fetch ( featureInfoUrl , {
@@ -338,7 +359,7 @@ export const useCoordinateInfo = ({
338359 }
339360
340361 return results ;
341- } , [ map , viewResolution , viewProjection , wmsMapLayers , wmtsMapLayers ,
362+ } , [ map , viewResolution , viewProjection , wmsMapLayerUids , wmtsMapLayerUids ,
342363 getInfoFormat , featureCount , fetchOpts , drillDown ] ) ;
343364
344365 const getResultsFromWfsLayers = useCallback ( async (
@@ -350,11 +371,16 @@ export const useCoordinateInfo = ({
350371
351372 const results : FeatureLayerResult [ ] = [ ] ;
352373
353- for ( const layer of wfsMapLayers ) {
374+ for ( const layerId of wfsMapLayerUids ) {
354375 if ( ! drillDown && results . length > 0 ) {
355376 break ;
356377 }
357378
379+ const layer = map . getAllLayers ( ) . find ( l => getUid ( l ) === layerId ) as WfsLayer | undefined ;
380+ if ( ! layer ) {
381+ continue ;
382+ }
383+
358384 const wfsLayerSource = layer . getSource ( ) ;
359385 if ( ! wfsLayerSource ) {
360386 continue ;
@@ -368,7 +394,7 @@ export const useCoordinateInfo = ({
368394 }
369395
370396 return results ;
371- } , [ map , viewProjection , wfsMapLayers , drillDown ] ) ;
397+ } , [ map , viewProjection , wfsMapLayerUids , drillDown ] ) ;
372398
373399 /**
374400 * Event handler for map events (click, double-click, pointer rest) that retrieves the coordinate of the
@@ -393,18 +419,25 @@ export const useCoordinateInfo = ({
393419
394420 const clonedCoordinate = _cloneDeep ( coordinate ) ;
395421 const clonedPixelCoordinate = _cloneDeep ( evtPixelCoordinate ?? pixel ) ;
396- setClickCoordinate ( clonedCoordinate ) ;
422+ setMapCoordinate ( clonedCoordinate ) ;
397423 setPixelCoordinate ( clonedPixelCoordinate ) ;
398424 } , [ clickEvent , map , viewProjection , viewResolution ] ) ;
399425
426+ /**
427+ * Resets featureResults when mapCoordinate changes.
428+ */
400429 useEffect ( ( ) => {
401- if ( ! _isNil ( clickCoordinate ) ) {
430+ if ( ! _isNil ( mapCoordinate ) ) {
402431 setFeatureResults ( undefined ) ;
403432 }
404- } , [ clickCoordinate ] ) ;
433+ } , [ mapCoordinate ] ) ;
405434
406435 useEffect ( ( ) => {
407- if ( _isNil ( clickCoordinate ) || _isNil ( map ) || orderedLayers ?. length === 0 ) {
436+ if ( loading ) {
437+ return ;
438+ }
439+
440+ if ( _isNil ( mapCoordinate ) || _isNil ( map ) || orderedLayerUids ?. length === 0 ) {
408441 return ;
409442 }
410443
@@ -415,37 +448,47 @@ export const useCoordinateInfo = ({
415448 abortControllers . current . forEach ( controller => controller . abort ( ) ) ;
416449 abortControllers . current . clear ( ) ;
417450
418- orderedLayers . forEach ( layer => {
419- const layerId = getUid ( layer ) ;
451+ orderedLayerUids . forEach ( uid => {
420452 const abortController = new AbortController ( ) ;
421- abortControllers . current . set ( layerId , abortController ) ;
453+ abortControllers . current . set ( uid , abortController ) ;
422454 } ) ;
423455
424456 const fetchFeatures = async ( ) => {
425457 try {
426458 setLoading ( true ) ;
459+ setFeatureResults ( undefined ) ;
427460
428461 const promises : Promise < FeatureLayerResult [ ] > [ ] = [ ] ;
462+ const allRelevantLayerUids = [ ...wfsMapLayerUids , ...wmtsMapLayerUids , ...wmsMapLayerUids ] ;
463+
464+ for ( const uid of orderedLayerUids ) {
465+ const layerId = allRelevantLayerUids . find ( id => id === uid ) ;
466+ const layer = map . getAllLayers ( ) . find ( l => getUid ( l ) === layerId ) ;
429467
430- for ( const layer of orderedLayers ) {
468+ if ( ! layer ) {
469+ continue ;
470+ }
431471 if ( isWmsLayer ( layer ) ) {
432- promises . push ( getResultsFromImageLayers ( clickCoordinate , true ) ) ;
472+ promises . push ( getResultsFromImageLayers ( mapCoordinate , true ) ) ;
433473 } else if ( isWmtsLayer ( layer ) ) {
434- promises . push ( getResultsFromImageLayers ( clickCoordinate , false ) ) ;
474+ promises . push ( getResultsFromImageLayers ( mapCoordinate , false ) ) ;
435475 } else if ( isWfsLayer ( layer ) ) {
436- promises . push ( getResultsFromWfsLayers ( clickCoordinate ) ) ;
437- }
438-
439- if ( ! drillDown ) {
440- break ;
476+ promises . push ( getResultsFromWfsLayers ( mapCoordinate ) ) ;
441477 }
442478 }
443479
444- let allResults : FeatureLayerResult [ ] [ ] ;
445- if ( drillDown ) {
446- allResults = await Promise . all ( promises ) ;
447- } else {
448- const firstResult = await Promise . race ( promises ) ;
480+ let allResults : FeatureLayerResult [ ] [ ] = await Promise . all ( promises ) ;
481+ allResults = await Promise . all ( promises ) ;
482+
483+ if ( ! drillDown ) {
484+ // filter empty results, order by layer index and return the first layer found
485+ const firstResult = allResults
486+ . filter ( r => r . length > 0 )
487+ . sort ( ( a , b ) => {
488+ const aIdx = orderedLayerUids . indexOf ( getUid ( a [ 0 ] . layer ) ) ;
489+ const bIdx = orderedLayerUids . indexOf ( getUid ( b [ 0 ] . layer ) ) ;
490+ return aIdx - bIdx ;
491+ } ) [ 0 ] ?? [ ] ;
449492 allResults = [ firstResult ] ;
450493 }
451494
@@ -468,10 +511,13 @@ export const useCoordinateInfo = ({
468511 } ) ;
469512
470513 } , [
471- clickCoordinate , drillDown , featureResults , getResultsFromImageLayers , getResultsFromWfsLayers , map , orderedLayers ,
472- onError , onSuccess
514+ mapCoordinate , drillDown , featureResults , getResultsFromImageLayers , getResultsFromWfsLayers , map , orderedLayerUids ,
515+ onError , onSuccess , loading , wfsMapLayerUids , wmsMapLayerUids , wmtsMapLayerUids
473516 ] ) ;
474517
518+ /**
519+ * (Re)creates map event listeners whenever relevant props change (active, drilldown, clickEvent).
520+ */
475521 useEffect ( ( ) => {
476522 let keyMove : EventsKey | undefined ;
477523 let keyRest : EventsKey | undefined ;
@@ -481,11 +527,11 @@ export const useCoordinateInfo = ({
481527 keyClick = map ?. on ( clickEvent , handleMapEvent ) ;
482528 }
483529
484- if ( registerOnPointerMove ) {
530+ if ( registerOnPointerMove && ! drillDown ) {
485531 keyMove = map ?. on ( 'pointermove' , onPointerMove ) ;
486532 }
487533
488- if ( registerOnPointerRest ) {
534+ if ( registerOnPointerRest && ! drillDown ) {
489535 // @ts -expect-error pointerrest is no default event
490536 keyRest = map ?. on ( 'pointerrest' , handleMapEvent ) ;
491537 }
@@ -507,7 +553,7 @@ export const useCoordinateInfo = ({
507553 } ;
508554 } , [
509555 active , map , onPointerMove , handleMapEvent , registerOnClick ,
510- registerOnPointerMove , registerOnPointerRest , clickEvent
556+ registerOnPointerMove , registerOnPointerRest , clickEvent , drillDown
511557 ] ) ;
512558
513559 useEffect ( ( ) => {
@@ -518,6 +564,9 @@ export const useCoordinateInfo = ({
518564 } ;
519565 } , [ viewResolution ] ) ;
520566
567+ /**
568+ * Update mouse cursor when GFI is loading.
569+ */
521570 useEffect ( ( ) => {
522571 if ( _isNil ( map ) ) {
523572 return ;
@@ -528,7 +577,7 @@ export const useCoordinateInfo = ({
528577 // We want to propagate the state here so the variables do
529578 // not change on every render cycle.
530579 return {
531- clickCoordinate,
580+ clickCoordinate : mapCoordinate ,
532581 features : featureResults ,
533582 loading,
534583 pixelCoordinate
0 commit comments