Fit map to route bounds when opening a route in the planner
Agent-Logs-Url: https://github.com/trails-cool/trails/sessions/558ccff8-ed5d-432a-a5d3-aca49c0e531e Co-authored-by: stigi <13815+stigi@users.noreply.github.com>
This commit is contained in:
parent
9de1a05903
commit
1b9683752f
2 changed files with 46 additions and 0 deletions
|
|
@ -54,6 +54,27 @@ function MapExposer() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function RouteFitter({ coordinates }: { coordinates: [number, number, number][] | null }) {
|
||||||
|
const map = useMap();
|
||||||
|
const hasFitted = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (hasFitted.current || !coordinates || coordinates.length < 2) return;
|
||||||
|
|
||||||
|
// Coordinates are in [lon, lat, elevation] GeoJSON format
|
||||||
|
const bounds = L.latLngBounds(
|
||||||
|
coordinates.filter((c) => c.length >= 2).map((c) => [c[1]!, c[0]!] as [number, number]),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (bounds.isValid()) {
|
||||||
|
map.fitBounds(bounds, { padding: [50, 50], maxZoom: 16 });
|
||||||
|
hasFitted.current = true;
|
||||||
|
}
|
||||||
|
}, [coordinates, map]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function MapClickHandler({ onAdd, suppressRef }: { onAdd: (lat: number, lng: number) => void; suppressRef: React.RefObject<boolean> }) {
|
function MapClickHandler({ onAdd, suppressRef }: { onAdd: (lat: number, lng: number) => void; suppressRef: React.RefObject<boolean> }) {
|
||||||
useMapEvents({
|
useMapEvents({
|
||||||
click(e) {
|
click(e) {
|
||||||
|
|
@ -314,6 +335,7 @@ export function PlannerMap({ yjs, onRouteRequest, highlightPosition }: PlannerMa
|
||||||
</LayersControl>
|
</LayersControl>
|
||||||
|
|
||||||
<MapExposer />
|
<MapExposer />
|
||||||
|
<RouteFitter coordinates={routeCoordinates} />
|
||||||
<MapClickHandler onAdd={noGoDrawing ? () => {} : addWaypoint} suppressRef={suppressMapClickRef} />
|
<MapClickHandler onAdd={noGoDrawing ? () => {} : addWaypoint} suppressRef={suppressMapClickRef} />
|
||||||
<CursorTracker awareness={yjs.awareness} />
|
<CursorTracker awareness={yjs.awareness} />
|
||||||
<NoGoAreaLayer noGoAreas={yjs.noGoAreas} doc={yjs.doc} enabled={noGoDrawing} onToggle={toggleNoGoDraw} />
|
<NoGoAreaLayer noGoAreas={yjs.noGoAreas} doc={yjs.doc} enabled={noGoDrawing} onToggle={toggleNoGoDraw} />
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,30 @@ test.describe("Planner", () => {
|
||||||
await expect(page.getByTitle("Draw no-go area")).toBeVisible();
|
await expect(page.getByTitle("Draw no-go area")).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("map zooms to fit the route when opened with initial waypoints", async ({ page, request }) => {
|
||||||
|
const sessionResp = await request.post("/api/sessions", { data: {} });
|
||||||
|
const { url } = await sessionResp.json();
|
||||||
|
|
||||||
|
const waypoints = [
|
||||||
|
{ lat: 52.520, lon: 13.405 },
|
||||||
|
{ lat: 52.515, lon: 13.351 },
|
||||||
|
];
|
||||||
|
await page.goto(`${url}?waypoints=${encodeURIComponent(JSON.stringify(waypoints))}`);
|
||||||
|
|
||||||
|
await expect(page.locator(".leaflet-container")).toBeVisible({ timeout: 10000 });
|
||||||
|
await expect(page.getByText("Connected")).toBeVisible({ timeout: 15000 });
|
||||||
|
// Wait for route to compute and fit
|
||||||
|
await expect(page.getByText(/\d+\.\d+ km/)).toBeVisible({ timeout: 20000 });
|
||||||
|
|
||||||
|
// The map should have zoomed in to the route bounds (zoom > default 6)
|
||||||
|
const zoom = await page.evaluate(() => {
|
||||||
|
const map = (window as any).__leafletMap;
|
||||||
|
return map ? map.getZoom() : null;
|
||||||
|
});
|
||||||
|
expect(zoom).not.toBeNull();
|
||||||
|
expect(zoom).toBeGreaterThan(6);
|
||||||
|
});
|
||||||
|
|
||||||
test("can create session with initial waypoints", async ({ request }) => {
|
test("can create session with initial waypoints", async ({ request }) => {
|
||||||
const response = await request.post("/api/sessions", {
|
const response = await request.post("/api/sessions", {
|
||||||
data: {
|
data: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue