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"
25import { Source , Layer , useMap } from "react-map-gl/maplibre"
36import turfLength from "@turf/length"
47import {
@@ -13,18 +16,15 @@ import { generateMapLibreId } from "../../js/maplibre"
1316export default function MaplibreRuler ( { onLengthUpdate } ) {
1417 const { map } = useMap ( )
1518 const [ geojson , setGeojson ] = useState ( turfFeatureCollection ( [ ] ) )
19+ const projectionCoordsRef = useRef ( [ ] )
1620
17- const cssCustomProps = useCssCustomProperties ( [
18- `--color-black` ,
19- `--color-white` ,
20- ] )
21+ const cssCustomProps = useCssCustomProperties ( [ `--color-black` ] )
2122
2223 const mapClick = useCallback (
2324 ( e ) => {
2425 const features = map . queryRenderedFeatures ( e . point , {
2526 layers : [ `fu-ruler-points` ] ,
2627 } )
27-
2828 const newGeojson = structuredClone ( geojson )
2929
3030 // remove the line as it's always the last feature
@@ -54,19 +54,39 @@ export default function MaplibreRuler({ onLengthUpdate }) {
5454 onLengthUpdate ( turfLength ( lineString , { units : `kilometers` } ) )
5555 } else onLengthUpdate ?. ( 0 )
5656
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+
5765 setGeojson ( newGeojson )
5866 } ,
5967 [ geojson , map , onLengthUpdate ]
6068 )
6169
6270 const mapMouseMove = useCallback (
6371 ( e ) => {
64- // TODO: implement projection
6572 const features = map . queryRenderedFeatures ( e . point , {
6673 layers : [ `fu-ruler-points` ] ,
6774 } )
6875
6976 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 ) )
7090 } ,
7191 [ map ]
7292 )
@@ -86,8 +106,24 @@ export default function MaplibreRuler({ onLengthUpdate }) {
86106
87107 return (
88108 < >
109+ < Source
110+ id = "fu-ruler-projection"
111+ type = "geojson"
112+ data = { turfFeatureCollection ( [ ] ) }
113+ />
114+
89115 < Source id = "fu-ruler" type = "geojson" data = { geojson } />
90116
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+
91127 < Layer
92128 source = "fu-ruler"
93129 id = "fu-ruler-points"
0 commit comments