fix: add anchor for station
This commit is contained in:
@@ -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,8 +1969,8 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
: 3;
|
||||
|
||||
return (
|
||||
<div key={station.id}>
|
||||
<div
|
||||
key={station.id}
|
||||
onMouseEnter={() => setHoveredStationId(station.id)}
|
||||
onMouseLeave={() =>
|
||||
setHoveredStationId((prev) =>
|
||||
@@ -2029,6 +2029,7 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
fontSize: primaryFontSize,
|
||||
textShadow: "0 0 4px rgba(0,0,0,0.6)",
|
||||
pointerEvents: "none",
|
||||
whiteSpace: "nowrap",
|
||||
}}
|
||||
>
|
||||
{station.name}
|
||||
@@ -2103,6 +2104,7 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
? "#e0e0e0"
|
||||
: "transparent",
|
||||
borderRadius: 4,
|
||||
whiteSpace: "nowrap",
|
||||
color: "black",
|
||||
fontWeight: 500,
|
||||
userSelect: "none",
|
||||
@@ -2115,6 +2117,7 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -283,16 +283,12 @@ class SnapshotStore {
|
||||
{ headers: { "X-Request-ID": this.lastRequestId } }
|
||||
);
|
||||
|
||||
// Не ждем здесь, так как статус будет загружен в компоненте
|
||||
// this.getSnapshotStatus(response.data.ID);
|
||||
|
||||
return response.data.ID;
|
||||
};
|
||||
|
||||
getSnapshotStatus = async (id: string) => {
|
||||
const response = await authInstance.get(`/snapshots/status/${id}`);
|
||||
|
||||
console.log(response.data);
|
||||
runInAction(() => {
|
||||
this.snapshotStatus = response.data;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user