move crosshair on trail hover

This commit is contained in:
Christian Beutel
2025-01-12 15:29:37 +01:00
parent 860e634a03
commit 7005b3677f
3 changed files with 92 additions and 28 deletions

View File

@@ -185,7 +185,7 @@
}
refreshElevationProfile();
if (showElevation) {
if (showElevation && data.length) {
epc?.showProfile();
}
@@ -212,6 +212,8 @@
} else {
flyToBounds();
}
} else if(drawing && activeTrail !== null && mapLoaded) {
addCaretLayer(trails[activeTrail]?.id)
}
}
@@ -283,6 +285,7 @@
map?.off("mouseleave", id, layers[id].listener.onLeave!);
map?.off("mouseup", id, layers[id].listener.onMouseUp!);
map?.off("mousemove", id, layers[id].listener.onMouseMove!);
map?.off("mousedown", id, layers[id].listener.onMouseDown!);
delete layers[id];
}
@@ -347,10 +350,9 @@
highlightTrail(id, trails[activeTrail ?? -1]?.id == id);
layers[id].listener.onLeave = (e) => unHighlightTrail(id);
layers[id].listener.onMouseUp = (e) => {
activeTrail = trails.indexOf(trail);
activeTrail = trails.findIndex(t => t.id == trail.id);
};
layers[id].listener.onMouseMove =
moveElevationMarkerToCursorPosition;
layers[id].listener.onMouseMove = moveCrosshairToCursorPosition;
layers[id].listener.onMouseDown = (e) => handDragStart(e, id);
map.on("mouseenter", id, layers[id].listener.onEnter);
@@ -365,6 +367,11 @@
}
}
function moveCrosshairToCursorPosition(e: M.MapMouseEvent) {
epc?.moveCrosshair(e.lngLat.lat, e.lngLat.lng);
moveElevationMarkerToCursorPosition(e);
}
function moveElevationMarkerToCursorPosition(e: M.MapMouseEvent) {
elevationMarker.setLngLat(e.lngLat);
}
@@ -394,6 +401,7 @@
function handleDragEnd(e: M.MapMouseEvent) {
map?.off("mousemove", moveElevationMarkerToCursorPosition);
epc?.hideCrosshair();
dispatch("segmentDragEnd", { segment: draggingSegment, event: e });
draggingSegment = null;
}
@@ -459,14 +467,14 @@
return;
}
elevationMarker.setOpacity("0");
epc?.hideCrosshair();
hoveringTrail = false;
map?.setPaintProperty(id, "line-width", 5);
// map?.setPaintProperty(id, "line-color", "#648ad5");
}
function focusTrail(trail: Trail) {
activeTrail = trails.findIndex(t => t.id == trail.id);
activeTrail = trails.findIndex((t) => t.id == trail.id);
if (activeTrail < 0) {
activeTrail = null;
return;
@@ -479,7 +487,6 @@
dispatch("select", trail);
try {
highlightTrail(trail.id!);
refreshElevationProfile();
if (showElevation) {
epc?.showProfile();
@@ -488,7 +495,7 @@
addCaretLayer(trail.id!);
flyToBounds();
} catch (e) {
console.warn(e)
console.warn(e);
}
}
@@ -743,7 +750,11 @@
elevationMarker.setOpacity("0");
},
onMove: (data) => {
elevationMarker.setLngLat(data.position as M.LngLatLike);
if (!hoveringTrail) {
elevationMarker.setLngLat(
data.position as M.LngLatLike,
);
}
},
});
map.addControl(epc);

View File

@@ -2,7 +2,7 @@ import { type ControlPosition, type IControl } from "maplibre-gl";
import * as M from "maplibre-gl";
import { ElevationProfile, type ElevationProfileOptions } from "./elevationprofile";
// @ts-ignore
import type { GeoJsonObject } from "geojson";
import type { GeoJsonObject, Position } from "geojson";
import type { Waypoint } from "$lib/models/waypoint";
/**
@@ -189,6 +189,30 @@ export class ElevationProfileControl implements IControl {
this.isProfileShown = false;
}
moveCrosshair(lat: number, lon: number) {
if (!this.elevationProfileChart) {
return;
}
const chart = this.elevationProfileChart.chart
const point = this.elevationProfileChart.getChartCoordinatesFromPosition(lat, lon)
if (point == null) {
return;
}
const rectangle = chart.canvas.getBoundingClientRect();
const mouseMoveEvent = new MouseEvent('mousemove', {
clientX: rectangle.left + point[0],
clientY: rectangle.top + point[1]
});
chart.canvas.dispatchEvent(mouseMoveEvent);
}
hideCrosshair() {
const mouseOutEvent = new MouseEvent('mouseout');
return this.elevationProfileChart?.chart.canvas.dispatchEvent(mouseOutEvent);
}
onRemove(): void {
// remove button
if (this.buttonContainer?.parentNode) {

View File

@@ -358,7 +358,7 @@ const elevationProfileDefaultOptions: ElevationProfileOptions = {
export class ElevationProfile {
private canvas: HTMLCanvasElement;
private settings: ElevationProfileOptions;
private chart: Chart<"line", Array<number>, number>;
public chart: Chart<"line", Array<number>, number>;
private elevatedPositions: Position[] = [];
private elevatedPositionsAdjustedUnit: Position[] = [];
private cumulatedDistance: number[] = [];
@@ -483,7 +483,6 @@ export class ElevationProfile {
},
onHover: (_e, item) => {
if (typeof this.settings.onMove !== "function") return;
try {
const i = item[0].index;
@@ -753,6 +752,33 @@ export class ElevationProfile {
}
}
getChartCoordinatesFromPosition(lat: number, lon: number) {
let minDistance = Infinity
let bestCandiateIndex: number = -1
for (let i = 0; i < this.elevatedPositionsAdjustedUnit.length; i++) {
const p = this.elevatedPositionsAdjustedUnit[i];
const deltaLat = lat - p[1];
const deltaLon = lon - p[0];
const distance = deltaLat * deltaLat + deltaLon * deltaLon;
if (distance < minDistance) {
minDistance = distance;
bestCandiateIndex = i
}
};
if (bestCandiateIndex < 0) {
return null;
}
const meta = this.chart.getDatasetMeta(0);
const element = meta.data[bestCandiateIndex];
if (element) {
return [element.x, element.y];
}
return null;
}
gradientFromElevation(chart: Chart, force: boolean = false) {
const ctx = chart.ctx;
const chartArea = chart.chartArea;
@@ -954,6 +980,7 @@ export class ElevationProfile {
const timeStart = this.times[segmentStartIndex]
const timeEnd = this.times[i]
if (timeStart && timeEnd) {
const timeDelta = (timeEnd.getTime() - timeStart.getTime()) / 1000
speed = (distanceDelta / timeDelta)
@@ -964,6 +991,8 @@ export class ElevationProfile {
}
}
}
// Apply the same grade to all positions within this segment
for (let j = segmentStartIndex; j <= i; j++) {