fix: map preview scale
This commit is contained in:
@@ -216,6 +216,12 @@ const rotateVertices = (
|
||||
const DRAG_THRESHOLD_PX = 4;
|
||||
const ICON_SIZE_MIN = 1;
|
||||
const ICON_SIZE_MAX = 300;
|
||||
const DEBUG_WEBGL_ROUTE_MAP = true;
|
||||
|
||||
const debugWebglLog = (...args: unknown[]) => {
|
||||
if (!DEBUG_WEBGL_ROUTE_MAP) return;
|
||||
console.log("[WebGLRouteMapPrototype]", ...args);
|
||||
};
|
||||
|
||||
type StationDragState = {
|
||||
stationId: number;
|
||||
@@ -735,7 +741,16 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
next: Transform,
|
||||
options?: { immediate?: boolean; skipClamp?: boolean },
|
||||
) => {
|
||||
const prevTransform = transformRef.current;
|
||||
const adjusted = options?.skipClamp ? next : clampTransformScale(next);
|
||||
debugWebglLog("updateTransform", {
|
||||
immediate: Boolean(options?.immediate),
|
||||
skipClamp: Boolean(options?.skipClamp),
|
||||
prevScale: prevTransform?.scale ?? null,
|
||||
nextScale: adjusted.scale,
|
||||
prevTranslation: prevTransform?.translation ?? null,
|
||||
nextTranslation: adjusted.translation,
|
||||
});
|
||||
|
||||
transformRef.current = adjusted;
|
||||
if (options?.immediate) {
|
||||
@@ -1268,10 +1283,7 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
}
|
||||
|
||||
const safePercent = Math.max(ICON_SIZE_MIN, currentPercent);
|
||||
const baseSizePxAt100 = Math.max(
|
||||
1,
|
||||
initialSizePx / (safePercent / 100),
|
||||
);
|
||||
const baseSizePxAt100 = Math.max(1, initialSizePx / (safePercent / 100));
|
||||
|
||||
sightIconResizeStateRef.current = {
|
||||
sightId,
|
||||
@@ -1376,6 +1388,10 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
|
||||
if (typeof ResizeObserver === "undefined") {
|
||||
const handleResize = () => {
|
||||
debugWebglLog("container resize (fallback)", {
|
||||
width: container.clientWidth,
|
||||
height: container.clientHeight,
|
||||
});
|
||||
setCanvasSize({
|
||||
width: container.clientWidth,
|
||||
height: container.clientHeight,
|
||||
@@ -1389,6 +1405,7 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
const observer = new ResizeObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
const { width, height } = entry.contentRect;
|
||||
debugWebglLog("container resize", { width, height });
|
||||
setCanvasSize({ width, height });
|
||||
}
|
||||
});
|
||||
@@ -1418,6 +1435,15 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
const dpr = Math.max(1, window.devicePixelRatio || 1);
|
||||
const displayWidth = Math.max(1, Math.floor(canvasSize.width * dpr));
|
||||
const displayHeight = Math.max(1, Math.floor(canvasSize.height * dpr));
|
||||
debugWebglLog("drawScene:start", {
|
||||
cssCanvasWidth: canvasSize.width,
|
||||
cssCanvasHeight: canvasSize.height,
|
||||
dpr,
|
||||
displayWidth,
|
||||
displayHeight,
|
||||
routeVerticesCount: rotatedRouteVertices.length / 2,
|
||||
stationVerticesCount: rotatedStationVertices.length / 2,
|
||||
});
|
||||
|
||||
if (canvas.width !== displayWidth || canvas.height !== displayHeight) {
|
||||
canvas.width = displayWidth;
|
||||
@@ -1531,6 +1557,11 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
}
|
||||
|
||||
const { scale, translation } = transform;
|
||||
debugWebglLog("drawScene:transform", {
|
||||
scale,
|
||||
translation,
|
||||
scaleLimits: scaleLimitsRef.current,
|
||||
});
|
||||
|
||||
const desiredRouteWidthCss = 7;
|
||||
const desiredStationDiameterCss = 12;
|
||||
@@ -1545,6 +1576,11 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
rotatedRouteVertices,
|
||||
lineWidth,
|
||||
);
|
||||
debugWebglLog("drawScene:route", {
|
||||
desiredRouteWidthCss,
|
||||
lineWidthWorldUnits: lineWidth,
|
||||
thickVerticesCount: thickVertices.length / 2,
|
||||
});
|
||||
if (thickVertices.length === 0) {
|
||||
gl.bufferData(gl.ARRAY_BUFFER, rotatedRouteVertices, gl.STATIC_DRAW);
|
||||
} else {
|
||||
@@ -1635,6 +1671,10 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
pointOuterSizePx,
|
||||
);
|
||||
}
|
||||
debugWebglLog("drawScene:stations", {
|
||||
pointOuterSizePx,
|
||||
pointInnerSizePx,
|
||||
});
|
||||
if (pointProgram.uniformLocations.u_color) {
|
||||
gl.uniform4f(
|
||||
pointProgram.uniformLocations.u_color,
|
||||
@@ -1814,6 +1854,87 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
drawScene();
|
||||
}, [drawScene]);
|
||||
|
||||
useEffect(() => {
|
||||
const camera =
|
||||
transformState ?? transformRef.current ?? lastTransformRef.current;
|
||||
if (!camera || !sightData?.length) return;
|
||||
|
||||
const routeIconSizePercent =
|
||||
routeData?.icon_size ?? originalRouteData?.icon_size ?? 100;
|
||||
|
||||
for (const sight of sightData) {
|
||||
const shouldUseCustomSightIcon =
|
||||
sight.is_default_icon === false && !isMediaIdEmpty(sight.icon);
|
||||
if (!shouldUseCustomSightIcon) continue;
|
||||
|
||||
const customSightIconScaleFactor =
|
||||
camera.scale / Math.max(customSightIconBaseScaleRef.current ?? 1, 1e-6);
|
||||
const sightIconSizePercent =
|
||||
liveSightIconSizes.get(sight.id) ??
|
||||
(typeof sight.icon_size === "number" && Number.isFinite(sight.icon_size)
|
||||
? sight.icon_size
|
||||
: routeIconSizePercent);
|
||||
const iconSizePx =
|
||||
30 *
|
||||
clamp(sightIconSizePercent / 100, 0.1, 10) *
|
||||
customSightIconScaleFactor;
|
||||
|
||||
debugWebglLog("custom sight icon size", {
|
||||
sightId: sight.id,
|
||||
cameraScale: camera.scale,
|
||||
baseScale: customSightIconBaseScaleRef.current,
|
||||
scaleFactor: customSightIconScaleFactor,
|
||||
iconPercent: sightIconSizePercent,
|
||||
iconSizePx,
|
||||
});
|
||||
}
|
||||
}, [
|
||||
sightData,
|
||||
liveSightIconSizes,
|
||||
transformState,
|
||||
routeData?.icon_size,
|
||||
originalRouteData?.icon_size,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!stationData?.ru?.length) return;
|
||||
|
||||
const fontSizePercent =
|
||||
routeData?.font_size ?? originalRouteData?.font_size ?? 100;
|
||||
const fontScale = fontSizePercent / 100;
|
||||
const baseStationIconSizePx = 16 * fontScale * 1.2;
|
||||
|
||||
for (const station of stationData.ru) {
|
||||
const hasCustomStationIcon = !isMediaIdEmpty(station.icon);
|
||||
if (!hasCustomStationIcon) continue;
|
||||
|
||||
const stationIconSizePercent =
|
||||
liveStationIconSizes.get(station.id) ??
|
||||
(typeof station.icon_size === "number" && Number.isFinite(station.icon_size)
|
||||
? station.icon_size
|
||||
: 100);
|
||||
const iconSizePx = Math.max(
|
||||
1,
|
||||
Math.round(
|
||||
baseStationIconSizePx * clamp(stationIconSizePercent / 100, 0.1, 10),
|
||||
),
|
||||
);
|
||||
|
||||
debugWebglLog("custom station icon size", {
|
||||
stationId: station.id,
|
||||
fontSizePercent,
|
||||
baseStationIconSizePx,
|
||||
iconPercent: stationIconSizePercent,
|
||||
iconSizePx,
|
||||
});
|
||||
}
|
||||
}, [
|
||||
stationData?.ru,
|
||||
liveStationIconSizes,
|
||||
routeData?.font_size,
|
||||
originalRouteData?.font_size,
|
||||
]);
|
||||
|
||||
const applyCenterFromCoordinates = useCallback(
|
||||
(latitude: number, longitude: number) => {
|
||||
const roundedLat = Math.round(latitude * 1e6) / 1e6;
|
||||
@@ -2572,8 +2693,7 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
const cssX = labelX / dpr;
|
||||
const cssY = labelY / dpr;
|
||||
const shouldUseCustomSightIcon =
|
||||
sight.is_default_icon === false &&
|
||||
!isMediaIdEmpty(sight.icon);
|
||||
sight.is_default_icon === false && !isMediaIdEmpty(sight.icon);
|
||||
const sightIconUrl = shouldUseCustomSightIcon
|
||||
? `${mediaBaseUrl}${sight.icon}/download?token=${mediaToken}`
|
||||
: SIGHT_ICON_URL;
|
||||
|
||||
Reference in New Issue
Block a user