diff --git a/src/pages/Route/route-preview/webgl-prototype/WebGLRouteMapPrototype.tsx b/src/pages/Route/route-preview/webgl-prototype/WebGLRouteMapPrototype.tsx index 9a1193e..65dc1e1 100644 --- a/src/pages/Route/route-preview/webgl-prototype/WebGLRouteMapPrototype.tsx +++ b/src/pages/Route/route-preview/webgl-prototype/WebGLRouteMapPrototype.tsx @@ -364,16 +364,19 @@ const computeViewTransform = ( return { scale, translation }; }; -const getAnchorFromOffset = ( - offsetX: number, - offsetY: number -): { x: number; y: number } => { - const length = Math.hypot(offsetX, offsetY); +const getAnchorFromOffset = (align: number): { x: number; y: number } => { + let anchorX: number; + if (align === 1) { + anchorX = 0; + } else if (align === 3) { + anchorX = 1; + } else { + anchorX = 0.5; + } - const nx = offsetX / length; - const ny = offsetY / length; + const anchorY = 0.5; - return { x: (1 - nx) / 2, y: (1 - ny) / 2 }; + return { x: anchorX, y: anchorY }; }; const backgroundColor = toColor(BACKGROUND_COLOR); @@ -665,24 +668,8 @@ export const WebGLRouteMapPrototype = observer(() => { next: Transform, options?: { immediate?: boolean; skipClamp?: boolean } ) => { - console.log("🔄 updateTransform вызван", { - inputTransform: next, - options, - stackTrace: new Error().stack?.split("\n").slice(1, 4).join("\n"), - }); - const adjusted = options?.skipClamp ? next : clampTransformScale(next); - if (adjusted !== next && !options?.skipClamp) { - console.log( - "🔄 updateTransform: transform изменен после clampTransformScale", - { - before: next, - after: adjusted, - } - ); - } - transformRef.current = adjusted; if (options?.immediate) { flushSync(() => { @@ -732,18 +719,21 @@ export const WebGLRouteMapPrototype = observer(() => { event.preventDefault(); - const world = getWorldPosition( - event.clientX, - event.clientY, - state.camera - ); - if (!world) return; + const stationScreenX = + state.rotatedBase.x * state.camera.scale + state.camera.translation.x; + const stationScreenY = + state.rotatedBase.y * state.camera.scale + state.camera.translation.y; - const adjustedWorldX = world.x - state.pointerDelta.x; - const adjustedWorldY = world.y - state.pointerDelta.y; + const canvas = canvasRef.current; + if (!canvas) return; + const rect = canvas.getBoundingClientRect(); + const scaleX = canvas.width / Math.max(rect.width, 1); + const scaleY = canvas.height / Math.max(rect.height, 1); + const pointerScreenX = (event.clientX - rect.left) * scaleX; + const pointerScreenY = (event.clientY - rect.top) * scaleY; - const newOffsetX = adjustedWorldX - state.rotatedBase.x; - const newOffsetY = adjustedWorldY - state.rotatedBase.y; + const newOffsetX = pointerScreenX - stationScreenX - state.pointerDelta.x; + const newOffsetY = pointerScreenY - stationScreenY - state.pointerDelta.y; state.lastOffset = { x: newOffsetX, y: newOffsetY }; setLiveStationOffsets((prev) => { @@ -810,19 +800,25 @@ export const WebGLRouteMapPrototype = observer(() => { suppressAutoFitRef.current = true; - const pointerWorld = getWorldPosition( - event.clientX, - event.clientY, - camera - ); - const labelWorldX = rotatedBase.x + currentOffset.x; - const labelWorldY = rotatedBase.y + currentOffset.y; - const pointerDelta = pointerWorld - ? { - x: pointerWorld.x - labelWorldX, - y: pointerWorld.y - labelWorldY, - } - : { x: 0, y: 0 }; + const stationScreenX = + rotatedBase.x * camera.scale + camera.translation.x; + const stationScreenY = + rotatedBase.y * camera.scale + camera.translation.y; + const labelScreenX = stationScreenX + currentOffset.x; + const labelScreenY = stationScreenY + currentOffset.y; + + const canvas = canvasRef.current; + if (!canvas) return; + const rect = canvas.getBoundingClientRect(); + const scaleX = canvas.width / Math.max(rect.width, 1); + const scaleY = canvas.height / Math.max(rect.height, 1); + const pointerScreenX = (event.clientX - rect.left) * scaleX; + const pointerScreenY = (event.clientY - rect.top) * scaleY; + + const pointerDelta = { + x: pointerScreenX - labelScreenX, + y: pointerScreenY - labelScreenY, + }; const captureTarget = event.currentTarget; if (captureTarget.setPointerCapture) { @@ -1050,7 +1046,6 @@ export const WebGLRouteMapPrototype = observer(() => { canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); if (!(gl instanceof WebGLRenderingContext)) { - console.error("WebGL is not supported in this browser"); return; } @@ -1074,7 +1069,7 @@ export const WebGLRouteMapPrototype = observer(() => { lineBufferRef.current = gl.createBuffer(); pointBufferRef.current = gl.createBuffer(); } catch (error) { - console.error("Failed to initialize WebGL", error); + // console.error("Failed to initialize WebGL", error); } }, []); @@ -1912,17 +1907,23 @@ export const WebGLRouteMapPrototype = observer(() => { ? liveStationOffset.y : baseOffsetY; - const labelX = - (rotatedX + offsetX) * camera.scale + camera.translation.x; - const labelY = - (rotatedY + offsetY) * camera.scale + camera.translation.y; + const stationScreenX = + rotatedX * camera.scale + camera.translation.x; + const stationScreenY = + rotatedY * camera.scale + camera.translation.y; - const anchor = getAnchorFromOffset(offsetX, offsetY); + const labelX = stationScreenX + offsetX; + const labelY = stationScreenY + offsetY; + + const backendAlign = station.align; + + const anchor = getAnchorFromOffset(backendAlign ?? 2); const transformCss = `translate(${-anchor.x * 100}%, ${ -anchor.y * 100 }%)`; const dpr = Math.max(1, window.devicePixelRatio || 1); + const cssX = labelX / dpr; const cssY = labelY / dpr; const rotationCss = `${rotationAngle}rad`; @@ -1943,7 +1944,6 @@ export const WebGLRouteMapPrototype = observer(() => { const secondaryMarginTop = 5 * fontScale; - const backendAlign = station.align; const alignmentFromData: StationAlignment = backendAlign === 1 ? "left" @@ -1969,151 +1969,154 @@ export const WebGLRouteMapPrototype = observer(() => { : 3; return ( -