99 lines
2.9 KiB
TypeScript
99 lines
2.9 KiB
TypeScript
import type { Map as MapLibreMap, PaddingOptions } from "maplibre-gl";
|
|
import {
|
|
getWorkbenchCameraPadding
|
|
} from "../layout/workbench-layout";
|
|
import { WATER_NETWORK_GLOBAL_VIEW } from "./sources";
|
|
|
|
type LngLatBounds = [[number, number], [number, number]];
|
|
type WebMercatorBbox = readonly [number, number, number, number];
|
|
|
|
export type NetworkViewParams = {
|
|
bbox3857: WebMercatorBbox;
|
|
};
|
|
|
|
const WEB_MERCATOR_RADIUS = 6378137;
|
|
const GLOBAL_VIEW_MAX_ZOOM = 12;
|
|
const GLOBAL_VIEW_PADDING: PaddingOptions = { top: 48, right: 48, bottom: 48, left: 48 };
|
|
export function getWorkbenchPadding(leftPanelOpen: boolean, rightPanelOpen: boolean): PaddingOptions {
|
|
return getWorkbenchCameraPadding(1280, {
|
|
agentOpen: leftPanelOpen,
|
|
conditionOpen: rightPanelOpen
|
|
});
|
|
}
|
|
|
|
export function getResponsiveWorkbenchPadding(
|
|
map: MapLibreMap,
|
|
leftPanelOpen: boolean,
|
|
rightPanelOpen: boolean
|
|
): PaddingOptions {
|
|
const width = getMapViewportSize(map).width;
|
|
return getResponsivePadding(
|
|
map,
|
|
getWorkbenchCameraPadding(width, {
|
|
agentOpen: leftPanelOpen,
|
|
conditionOpen: rightPanelOpen
|
|
})
|
|
);
|
|
}
|
|
|
|
export function fitNetworkBounds(
|
|
map: MapLibreMap,
|
|
viewParams: NetworkViewParams = WATER_NETWORK_GLOBAL_VIEW,
|
|
padding: PaddingOptions = GLOBAL_VIEW_PADDING
|
|
) {
|
|
map.fitBounds(
|
|
getLngLatBoundsFromBbox3857(viewParams.bbox3857),
|
|
{
|
|
padding: getResponsivePadding(map, padding),
|
|
maxZoom: GLOBAL_VIEW_MAX_ZOOM,
|
|
duration: 600
|
|
}
|
|
);
|
|
}
|
|
|
|
export function getResponsivePadding(map: MapLibreMap, padding: PaddingOptions): PaddingOptions {
|
|
const { width, height } = getMapViewportSize(map);
|
|
const horizontalPadding = padding.left + padding.right;
|
|
const verticalPadding = padding.top + padding.bottom;
|
|
const maxHorizontalPadding = width * 0.58;
|
|
const maxVerticalPadding = height * 0.58;
|
|
const horizontalScale = horizontalPadding > 0 ? maxHorizontalPadding / horizontalPadding : 1;
|
|
const verticalScale = verticalPadding > 0 ? maxVerticalPadding / verticalPadding : 1;
|
|
const scale = Math.min(1, horizontalScale, verticalScale);
|
|
|
|
if (scale >= 1) {
|
|
return padding;
|
|
}
|
|
|
|
return {
|
|
top: Math.round(padding.top * scale),
|
|
right: Math.round(padding.right * scale),
|
|
bottom: Math.round(padding.bottom * scale),
|
|
left: Math.round(padding.left * scale)
|
|
};
|
|
}
|
|
|
|
function getMapViewportSize(map: MapLibreMap) {
|
|
const canvas = map.getCanvas();
|
|
return {
|
|
width: canvas.clientWidth || canvas.width,
|
|
height: canvas.clientHeight || canvas.height
|
|
};
|
|
}
|
|
|
|
function getLngLatBoundsFromBbox3857(bbox3857: WebMercatorBbox): LngLatBounds {
|
|
const [minX, minY, maxX, maxY] = bbox3857;
|
|
|
|
return [
|
|
webMercatorToLngLat(minX, minY),
|
|
webMercatorToLngLat(maxX, maxY)
|
|
];
|
|
}
|
|
|
|
function webMercatorToLngLat(x: number, y: number): [number, number] {
|
|
const lng = (x / WEB_MERCATOR_RADIUS) * (180 / Math.PI);
|
|
const lat = (2 * Math.atan(Math.exp(y / WEB_MERCATOR_RADIUS)) - Math.PI / 2) * (180 / Math.PI);
|
|
|
|
return [lng, lat];
|
|
}
|