feat(workbench): expand SCADA monitoring and investigation presentation
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import { Marker, type Map as MapLibreMap } from "maplibre-gl";
|
||||
import type { EventGpsCoordinate } from "./event-location-coordinate";
|
||||
|
||||
const arrowDirections: Record<string, [number, number]> = {
|
||||
ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1]
|
||||
};
|
||||
|
||||
export function createEventLocationMarker({ map, element, coordinate, disabled, onChange, onDragChange }: {
|
||||
map: MapLibreMap;
|
||||
element: HTMLButtonElement;
|
||||
coordinate: EventGpsCoordinate;
|
||||
disabled: boolean;
|
||||
onChange: (coordinate: EventGpsCoordinate) => void;
|
||||
onDragChange: (dragging: boolean) => void;
|
||||
}) {
|
||||
const marker = new Marker({ element, anchor: "bottom", draggable: !disabled })
|
||||
.setLngLat(coordinate)
|
||||
.addTo(map);
|
||||
element.setAttribute("aria-label", "事件位置标记,可拖拽调整");
|
||||
element.setAttribute("title", "拖拽调整事件位置,方向键微调,Shift 加速");
|
||||
element.setAttribute("aria-keyshortcuts", "ArrowUp ArrowDown ArrowLeft ArrowRight");
|
||||
marker.on("dragstart", () => {
|
||||
element.dataset.dragging = "true";
|
||||
onDragChange(true);
|
||||
});
|
||||
marker.on("dragend", () => {
|
||||
element.dataset.dragging = "false";
|
||||
onDragChange(false);
|
||||
const position = marker.getLngLat();
|
||||
onChange([normalizeLongitude(position.lng), clampLatitude(position.lat)]);
|
||||
});
|
||||
// Custom MapLibre markers own their keyboard interaction. Move in screen
|
||||
// pixels and consume arrows so adjusting the pin cannot also pan the map.
|
||||
element.onkeydown = (event) => {
|
||||
if (!marker.isDraggable() || event.altKey || event.ctrlKey || event.metaKey) return;
|
||||
const direction = arrowDirections[event.key];
|
||||
if (!direction) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const point = map.project(marker.getLngLat());
|
||||
const step = event.shiftKey ? 10 : 1;
|
||||
const position = map.unproject([point.x + direction[0] * step, point.y + direction[1] * step]);
|
||||
const next: EventGpsCoordinate = [normalizeLongitude(position.lng), clampLatitude(position.lat)];
|
||||
marker.setLngLat(next);
|
||||
onChange(next);
|
||||
};
|
||||
return marker;
|
||||
}
|
||||
|
||||
export function normalizeLongitude(longitude: number) {
|
||||
return ((longitude + 180) % 360 + 360) % 360 - 180;
|
||||
}
|
||||
|
||||
export function clampLatitude(latitude: number) {
|
||||
return Math.max(-90, Math.min(90, latitude));
|
||||
}
|
||||
Reference in New Issue
Block a user