import { divIcon, LatLngLiteral, LayerGroup, Map, marker, Marker } from "leaflet"; import { arrowClusterIcon, createArrow } from "$utils/arrow"; import { MarkerClusterGroup } from 'leaflet.markercluster/dist/leaflet.markercluster-src.js'; import { allwaysPositiveAngleDeg, angleBetweenPoints, distKm } from "$utils/geom"; interface KmMarksOptions { showMiddleMarkers: boolean, showEndMarker: boolean, kmMarksStep: number, } class Component extends LayerGroup { constructor(latlngs?: LatLngLiteral[], options?: KmMarksOptions){ super(); this.options = { showMiddleMarkers: true, showEndMarker: true, kmMarksStep: 10, ...(options || {}), } as KmMarksOptions; } setLatLngs = (latlngs: LatLngLiteral[]): void => { if (!this.map) return; this.marksLayer.clearLayers(); if (latlngs.length === 0) return; if (this.options.showMiddleMarkers) this.drawMiddleMarkers(latlngs); if (this.options.showEndMarker) this.drawEndMarker(latlngs); }; drawMiddleMarkers = (latlngs: LatLngLiteral[]) => { const kmMarks = {}; let last_km_mark = 0; latlngs.reduce((dist, current, index) => { if (index >= latlngs.length - 1) return; const next = latlngs[index + 1]; const diff = distKm(current, next); const sum = dist + diff; const rounded = Math.floor(sum / this.options.kmMarksStep) * this.options.kmMarksStep; const count = Math.floor((rounded - last_km_mark) / this.options.kmMarksStep); if (rounded > last_km_mark) { const angle = angleBetweenPoints( this.map.latLngToContainerPoint(current), this.map.latLngToContainerPoint(next), ); for (let i = 1; i <= count; i += 1) { const step = last_km_mark + (i * this.options.kmMarksStep); const shift = (step - dist) / diff; const coords = { lat: current.lat - ((current.lat - next.lat) * shift), lng: current.lng - ((current.lng - next.lng) * shift), }; kmMarks[step] = { ...coords, angle }; this.marksLayer.addLayer(this.createMiddleMarker(coords, angle, step)); } last_km_mark = rounded; } return sum; }, 0); console.log(kmMarks); }; createMiddleMarker = (latlng: LatLngLiteral, angle: number, distance: number): Marker => marker(latlng, { draggable: false, interactive: false, icon: divIcon({ html: `