Search code examples
javascripttypescriptleafletpolyline

Leaflet.js Find closest point on polyline and display it


I'm trying to find the closest Point on a Trackline corresponding to the position of the Mouse.

The UseCase is that the User needs to be able to create Markers which are positioned on the Track.

To implement the feature i've created a circleMarker to indicate the closest Point on the track and a dashed Polyline to connect the Mouse Position and the circle Marker. On the Mousemove event i update the position of the circleMarker and the Polyline using the Leaflet internal "closestLayerPoint" function and a bit of gps converting (LatLng To x,y and vice versa).

Everything works fine as long as i don't move the map( zoom out and zoom in with different center / drag the map). If i change the map position it feels like the old Trackposition is used to calculate the nearest point resulting in wrong positions.

Before moving the map: enter image description here

after moving the map: enter image description here

p.S.: You can't see my mouse position cause of Windows snipping tool. but that part is correct

   protected initTraceOptions(): void {
        this.trackTracing = {
            dot: L.circleMarker([0, 0], { radius: 10 }),
            trace: L.polyline([[0, 0], [0, 0]], {
                color: 'black',
                dashArray: '20, 20', dashOffset: '20',
            }),
            active: false,
            nearestPoint: null,
        };

    }    

    public activateTrackTracing(): void {
        if (this.trackTracing.active) {
            return;
        }
        this.map.off('mousemove');
        this.trackTracing.dot.addTo(this.map);
        this.trackTracing.trace.addTo(this.map);
        this.map.on('mousemove', this.updateTrackTracingOnMouseMove);
        this.trackTracing.active = true;
    }
    protected updateTrackTracingOnMouseMove = (event: L.LeafletMouseEvent): void => {
        this.trackTracing.nearestPoint = this.map.containerPointToLatLng(
            this.trackLine.polyLine.closestLayerPoint(event.containerPoint));
        this.trackTracing.dot.setLatLng(this.trackTracing.nearestPoint);
        this.trackTracing.trace.setLatLngs([event.latlng, this.trackTracing.nearestPoint]);
    };

Solution

  • i retrieved the point wrong, only retrieving it by its latlng doesn't display it correct, you can display the correct point by using this onEventFunction:

     protected updateTrackTracingOnMouseMove = (event: L.LeafletMouseEvent): void => {
        const eventLayerPoint = this.map.latLngToLayerPoint(this.map.containerPointToLatLng(event.containerPoint));
        this.trackTracing.nearestPoint = this.map.layerPointToLatLng(
            this.trackLine.polyLine.closestLayerPoint(eventLayerPoint));
        this.trackTracing.dot.setLatLng(this.trackTracing.nearestPoint);
        this.trackTracing.trace.setLatLngs([event.latlng, this.trackTracing.nearestPoint]);
    };