1
- import { useCallback , useEffect , useState } from "react"
1
+ // TODO:
2
+ // - custom cursors and/or descriptional tooltips on hover for points
3
+
4
+ import { useCallback , useEffect , useRef , useState } from "react"
2
5
import { Source , Layer , useMap } from "react-map-gl/maplibre"
3
6
import turfLength from "@turf/length"
4
7
import {
@@ -13,18 +16,15 @@ import { generateMapLibreId } from "../../js/maplibre"
13
16
export default function MaplibreRuler ( { onLengthUpdate } ) {
14
17
const { map } = useMap ( )
15
18
const [ geojson , setGeojson ] = useState ( turfFeatureCollection ( [ ] ) )
19
+ const projectionCoordsRef = useRef ( [ ] )
16
20
17
- const cssCustomProps = useCssCustomProperties ( [
18
- `--color-black` ,
19
- `--color-white` ,
20
- ] )
21
+ const cssCustomProps = useCssCustomProperties ( [ `--color-black` ] )
21
22
22
23
const mapClick = useCallback (
23
24
( e ) => {
24
25
const features = map . queryRenderedFeatures ( e . point , {
25
26
layers : [ `fu-ruler-points` ] ,
26
27
} )
27
-
28
28
const newGeojson = structuredClone ( geojson )
29
29
30
30
// remove the line as it's always the last feature
@@ -54,19 +54,39 @@ export default function MaplibreRuler({ onLengthUpdate }) {
54
54
onLengthUpdate ( turfLength ( lineString , { units : `kilometers` } ) )
55
55
} else onLengthUpdate ?. ( 0 )
56
56
57
+ // picking up the last point feature (the last in array is reserved for line)
58
+ projectionCoordsRef . current =
59
+ newGeojson . features [
60
+ newGeojson . features . length >= 3
61
+ ? newGeojson . features . length - 2
62
+ : newGeojson . features . length - 1
63
+ ] ?. geometry . coordinates || [ ]
64
+
57
65
setGeojson ( newGeojson )
58
66
} ,
59
67
[ geojson , map , onLengthUpdate ]
60
68
)
61
69
62
70
const mapMouseMove = useCallback (
63
71
( e ) => {
64
- // TODO: implement projection
65
72
const features = map . queryRenderedFeatures ( e . point , {
66
73
layers : [ `fu-ruler-points` ] ,
67
74
} )
68
75
69
76
map . getCanvas ( ) . style . cursor = features . length ? `pointer` : `crosshair`
77
+
78
+ const projectionFeatures = [ ]
79
+ if ( ! features . length && projectionCoordsRef . current . length )
80
+ projectionFeatures . push (
81
+ turfLineString ( [
82
+ projectionCoordsRef . current ,
83
+ [ e . lngLat . lng , e . lngLat . lat ] ,
84
+ ] )
85
+ )
86
+
87
+ map
88
+ . getSource ( `fu-ruler-projection` )
89
+ . setData ( turfFeatureCollection ( projectionFeatures ) )
70
90
} ,
71
91
[ map ]
72
92
)
@@ -86,8 +106,24 @@ export default function MaplibreRuler({ onLengthUpdate }) {
86
106
87
107
return (
88
108
< >
109
+ < Source
110
+ id = "fu-ruler-projection"
111
+ type = "geojson"
112
+ data = { turfFeatureCollection ( [ ] ) }
113
+ />
114
+
89
115
< Source id = "fu-ruler" type = "geojson" data = { geojson } />
90
116
117
+ < Layer
118
+ source = "fu-ruler-projection"
119
+ type = "line"
120
+ paint = { {
121
+ "line-color" : cssCustomProps [ `--color-black` ] ,
122
+ "line-width" : 3 ,
123
+ "line-dasharray" : [ 1 , 1 ] ,
124
+ } }
125
+ />
126
+
91
127
< Layer
92
128
source = "fu-ruler"
93
129
id = "fu-ruler-points"
0 commit comments