fix: Delete ai comments
This commit is contained in:
@@ -53,13 +53,11 @@ export const WebGLMap = observer(() => {
|
||||
|
||||
const cameraAnimationStore = useCameraAnimationStore();
|
||||
|
||||
// Ref для хранения ограничений масштаба
|
||||
const scaleLimitsRef = useRef({
|
||||
min: null as number | null,
|
||||
max: null as number | null,
|
||||
});
|
||||
|
||||
// Обновляем ограничения масштаба при изменении routeData
|
||||
useEffect(() => {
|
||||
if (
|
||||
routeData?.scale_min !== undefined &&
|
||||
@@ -72,7 +70,6 @@ export const WebGLMap = observer(() => {
|
||||
}
|
||||
}, [routeData?.scale_min, routeData?.scale_max]);
|
||||
|
||||
// Функция для ограничения масштаба значениями с бекенда
|
||||
const clampScale = useCallback((value: number) => {
|
||||
const { min, max } = scaleLimitsRef.current;
|
||||
|
||||
@@ -90,7 +87,6 @@ export const WebGLMap = observer(() => {
|
||||
const setPositionRef = useRef(setPosition);
|
||||
const setScaleRef = useRef(setScale);
|
||||
|
||||
// Обновляем refs при изменении функций
|
||||
useEffect(() => {
|
||||
setPositionRef.current = setPosition;
|
||||
}, [setPosition]);
|
||||
@@ -99,7 +95,6 @@ export const WebGLMap = observer(() => {
|
||||
setScaleRef.current = setScale;
|
||||
}, [setScale]);
|
||||
|
||||
// Логирование данных маршрута для отладки
|
||||
useEffect(() => {
|
||||
if (routeData) {
|
||||
}
|
||||
@@ -124,7 +119,6 @@ export const WebGLMap = observer(() => {
|
||||
setPositionImmediate: setYellowDotPositionImmediate,
|
||||
} = useAnimatedPolarPosition(0, 0, 800);
|
||||
|
||||
// Build transformed route path (map coords)
|
||||
const routePath = useMemo(() => {
|
||||
if (!routeData?.path || routeData?.path.length === 0)
|
||||
return new Float32Array();
|
||||
@@ -180,7 +174,6 @@ export const WebGLMap = observer(() => {
|
||||
rotationAngle,
|
||||
]);
|
||||
|
||||
// Настройка CameraAnimationStore callback - только один раз при монтировании
|
||||
useEffect(() => {
|
||||
const callback = (newPos: { x: number; y: number }, newZoom: number) => {
|
||||
setPosition(newPos);
|
||||
@@ -189,15 +182,13 @@ export const WebGLMap = observer(() => {
|
||||
|
||||
cameraAnimationStore.setUpdateCallback(callback);
|
||||
|
||||
// Синхронизируем начальное состояние только один раз
|
||||
cameraAnimationStore.syncState(position, scale);
|
||||
|
||||
return () => {
|
||||
cameraAnimationStore.setUpdateCallback(null);
|
||||
};
|
||||
}, []); // Пустой массив - выполняется только при монтировании
|
||||
}, []);
|
||||
|
||||
// Установка границ зума
|
||||
useEffect(() => {
|
||||
if (
|
||||
routeData?.scale_min !== undefined &&
|
||||
@@ -208,28 +199,23 @@ export const WebGLMap = observer(() => {
|
||||
}
|
||||
}, [routeData?.scale_min, routeData?.scale_max, cameraAnimationStore]);
|
||||
|
||||
// Автоматический режим - таймер для включения через 5 секунд бездействия
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
const timeSinceActivity = Date.now() - userActivityTimestamp;
|
||||
if (timeSinceActivity >= 5000 && !isAutoMode) {
|
||||
// 5 секунд бездействия - включаем авто режим
|
||||
setIsAutoMode(true);
|
||||
}
|
||||
}, 1000); // Проверяем каждую секунду
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [userActivityTimestamp, isAutoMode, setIsAutoMode]);
|
||||
|
||||
// Следование за желтой точкой с зумом при включенном авто режиме
|
||||
useEffect(() => {
|
||||
// Пропускаем обновление если анимация уже идет
|
||||
if (cameraAnimationStore.isActivelyAnimating) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAutoMode && transformedTramCoords && screenCenter) {
|
||||
// Преобразуем станции в формат для CameraAnimationStore
|
||||
const transformedStations = stationData
|
||||
? stationData
|
||||
.map((station: any) => {
|
||||
@@ -270,10 +256,8 @@ export const WebGLMap = observer(() => {
|
||||
cameraAnimationStore.setMaxZoom(scaleLimitsRef.current!.max);
|
||||
cameraAnimationStore.setMinZoom(scaleLimitsRef.current!.min);
|
||||
|
||||
// Синхронизируем текущее состояние камеры перед запуском анимации
|
||||
cameraAnimationStore.syncState(positionRef.current, scaleRef.current);
|
||||
|
||||
// Запускаем анимацию к желтой точке
|
||||
cameraAnimationStore.followTram(
|
||||
transformedTramCoords,
|
||||
screenCenter,
|
||||
@@ -293,7 +277,6 @@ export const WebGLMap = observer(() => {
|
||||
rotationAngle,
|
||||
]);
|
||||
|
||||
// Station label overlay positions (DOM overlay)
|
||||
const stationLabels = useMemo(() => {
|
||||
if (!stationData || !routeData)
|
||||
return [] as Array<{ x: number; y: number; name: string; sub?: string }>;
|
||||
@@ -356,7 +339,6 @@ export const WebGLMap = observer(() => {
|
||||
selectedLanguage as any,
|
||||
]);
|
||||
|
||||
// Build transformed stations (map coords)
|
||||
const stationPoints = useMemo(() => {
|
||||
if (!stationData || !routeData) return new Float32Array();
|
||||
const centerLat = routeData.center_latitude;
|
||||
@@ -386,7 +368,6 @@ export const WebGLMap = observer(() => {
|
||||
rotationAngle,
|
||||
]);
|
||||
|
||||
// Build transformed sights (map coords)
|
||||
const sightPoints = useMemo(() => {
|
||||
if (!sightData || !routeData) return new Float32Array();
|
||||
const centerLat = routeData.center_latitude;
|
||||
@@ -530,8 +511,6 @@ export const WebGLMap = observer(() => {
|
||||
const handleResize = () => {
|
||||
const changed = resizeCanvasToDisplaySize(canvas);
|
||||
if (!gl) return;
|
||||
// Update screen center when canvas size changes
|
||||
// Use physical pixels (canvas.width) instead of CSS pixels
|
||||
setScreenCenter({
|
||||
x: canvas.width / 2,
|
||||
y: canvas.height / 2,
|
||||
@@ -567,7 +546,6 @@ export const WebGLMap = observer(() => {
|
||||
const rx = x * cos - y * sin;
|
||||
const ry = x * sin + y * cos;
|
||||
|
||||
// В авторежиме используем анимацию, иначе мгновенное обновление
|
||||
if (isAutoMode) {
|
||||
animateYellowDotTo(rx, ry);
|
||||
} else {
|
||||
@@ -666,21 +644,18 @@ export const WebGLMap = observer(() => {
|
||||
|
||||
const vertexCount = routePath.length / 2;
|
||||
if (vertexCount > 1) {
|
||||
// Generate thick line geometry using triangles with proper joins
|
||||
const generateThickLine = (points: Float32Array, width: number) => {
|
||||
const vertices: number[] = [];
|
||||
const halfWidth = width / 2;
|
||||
|
||||
if (points.length < 4) return new Float32Array();
|
||||
|
||||
// Process each segment
|
||||
for (let i = 0; i < points.length - 2; i += 2) {
|
||||
const x1 = points[i];
|
||||
const y1 = points[i + 1];
|
||||
const x2 = points[i + 2];
|
||||
const y2 = points[i + 3];
|
||||
|
||||
// Calculate perpendicular vector
|
||||
const dx = x2 - x1;
|
||||
const dy = y2 - y1;
|
||||
const length = Math.sqrt(dx * dx + dy * dy);
|
||||
@@ -689,18 +664,14 @@ export const WebGLMap = observer(() => {
|
||||
const perpX = (-dy / length) * halfWidth;
|
||||
const perpY = (dx / length) * halfWidth;
|
||||
|
||||
// Create quad (two triangles) for this line segment
|
||||
// Triangle 1
|
||||
vertices.push(x1 + perpX, y1 + perpY);
|
||||
vertices.push(x1 - perpX, y1 - perpY);
|
||||
vertices.push(x2 + perpX, y2 + perpY);
|
||||
|
||||
// Triangle 2
|
||||
vertices.push(x1 - perpX, y1 - perpY);
|
||||
vertices.push(x2 - perpX, y2 - perpY);
|
||||
vertices.push(x2 + perpX, y2 + perpY);
|
||||
|
||||
// Add simple join triangles to fill gaps
|
||||
if (i < points.length - 4) {
|
||||
const x3 = points[i + 4];
|
||||
const y3 = points[i + 5];
|
||||
@@ -712,7 +683,6 @@ export const WebGLMap = observer(() => {
|
||||
const perpX2 = (-dy2 / length2) * halfWidth;
|
||||
const perpY2 = (dx2 / length2) * halfWidth;
|
||||
|
||||
// Simple join - just connect the endpoints
|
||||
vertices.push(x2 + perpX, y2 + perpY);
|
||||
vertices.push(x2 - perpX, y2 - perpY);
|
||||
vertices.push(x2 + perpX2, y2 + perpY2);
|
||||
@@ -734,22 +704,18 @@ export const WebGLMap = observer(() => {
|
||||
gl.uniform4f(uniforms.u_color, r1, g1, b1, 1);
|
||||
|
||||
if (tramSegIndex >= 0) {
|
||||
// Используем точную позицию желтой точки для определения конца красной линии
|
||||
const animatedPos = animatedYellowDotPosition;
|
||||
if (
|
||||
animatedPos &&
|
||||
animatedPos.x !== undefined &&
|
||||
animatedPos.y !== undefined
|
||||
) {
|
||||
// Создаем массив точек от начала маршрута до позиции желтой точки
|
||||
const passedPoints: number[] = [];
|
||||
|
||||
// Добавляем все точки до текущего сегмента
|
||||
for (let i = 0; i <= tramSegIndex; i++) {
|
||||
passedPoints.push(routePath[i * 2], routePath[i * 2 + 1]);
|
||||
}
|
||||
|
||||
// Добавляем точную позицию желтой точки как конечную точку
|
||||
passedPoints.push(animatedPos.x, animatedPos.y);
|
||||
|
||||
if (passedPoints.length >= 4) {
|
||||
@@ -768,7 +734,6 @@ export const WebGLMap = observer(() => {
|
||||
const b2 = (UNPASSED_STATION_COLOR & 0xff) / 255;
|
||||
gl.uniform4f(uniforms.u_color, r2, g2, b2, 1);
|
||||
|
||||
// Серая линия начинается точно от позиции желтой точки
|
||||
const animatedPos = animatedYellowDotPosition;
|
||||
if (
|
||||
animatedPos &&
|
||||
@@ -777,10 +742,8 @@ export const WebGLMap = observer(() => {
|
||||
) {
|
||||
const unpassedPoints: number[] = [];
|
||||
|
||||
// Добавляем позицию желтой точки как начальную точку серой линии
|
||||
unpassedPoints.push(animatedPos.x, animatedPos.y);
|
||||
|
||||
// Добавляем все точки после текущего сегмента
|
||||
for (let i = tramSegIndex + 1; i < vertexCount; i++) {
|
||||
unpassedPoints.push(routePath[i * 2], routePath[i * 2 + 1]);
|
||||
}
|
||||
@@ -796,7 +759,6 @@ export const WebGLMap = observer(() => {
|
||||
}
|
||||
}
|
||||
|
||||
// Draw stations
|
||||
if (stationPoints.length > 0) {
|
||||
gl.useProgram(pprog);
|
||||
const a_pos_pts = gl.getAttribLocation(pprog, "a_pos");
|
||||
@@ -814,7 +776,6 @@ export const WebGLMap = observer(() => {
|
||||
gl.enableVertexAttribArray(a_pos_pts);
|
||||
gl.vertexAttribPointer(a_pos_pts, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
// Draw station outlines (black background)
|
||||
gl.uniform1f(u_pointSize, 10 * scale * 1.5);
|
||||
const r_outline = ((BACKGROUND_COLOR >> 16) & 0xff) / 255;
|
||||
const g_outline = ((BACKGROUND_COLOR >> 8) & 0xff) / 255;
|
||||
@@ -822,15 +783,12 @@ export const WebGLMap = observer(() => {
|
||||
gl.uniform4f(u_color_pts, r_outline, g_outline, b_outline, 1);
|
||||
gl.drawArrays(gl.POINTS, 0, stationPoints.length / 2);
|
||||
|
||||
// Draw station cores (colored based on passed/unpassed)
|
||||
gl.uniform1f(u_pointSize, 8.0 * scale * 1.5);
|
||||
|
||||
// Draw passed stations (red)
|
||||
if (tramSegIndex >= 0) {
|
||||
const passedStations = [];
|
||||
for (let i = 0; i < stationData.length; i++) {
|
||||
if (i <= tramSegIndex) {
|
||||
// @ts-ignore
|
||||
passedStations.push(stationPoints[i * 2], stationPoints[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
@@ -848,13 +806,11 @@ export const WebGLMap = observer(() => {
|
||||
}
|
||||
}
|
||||
|
||||
// Draw unpassed stations (gray)
|
||||
if (tramSegIndex >= 0) {
|
||||
const unpassedStations = [];
|
||||
for (let i = 0; i < stationData.length; i++) {
|
||||
if (i > tramSegIndex) {
|
||||
unpassedStations.push(
|
||||
// @ts-ignore
|
||||
stationPoints[i * 2],
|
||||
stationPoints[i * 2 + 1]
|
||||
);
|
||||
@@ -873,7 +829,6 @@ export const WebGLMap = observer(() => {
|
||||
gl.drawArrays(gl.POINTS, 0, unpassedStations.length / 2);
|
||||
}
|
||||
} else {
|
||||
// If no tram position, draw all stations as unpassed
|
||||
const r_unpassed = ((UNPASSED_STATION_COLOR >> 16) & 0xff) / 255;
|
||||
const g_unpassed = ((UNPASSED_STATION_COLOR >> 8) & 0xff) / 255;
|
||||
const b_unpassed = (UNPASSED_STATION_COLOR & 0xff) / 255;
|
||||
@@ -1015,7 +970,6 @@ export const WebGLMap = observer(() => {
|
||||
if (passedStations.length)
|
||||
gl.drawArrays(gl.POINTS, 0, passedStations.length / 2);
|
||||
|
||||
// Draw black dots with white outline for terminal stations (startStopId and endStopId) - 5x larger
|
||||
if (
|
||||
stationData &&
|
||||
stationData.length > 0 &&
|
||||
@@ -1028,7 +982,6 @@ export const WebGLMap = observer(() => {
|
||||
const cos = Math.cos(rotationAngle);
|
||||
const sin = Math.sin(rotationAngle);
|
||||
|
||||
// Find terminal stations using startStopId and endStopId from context
|
||||
const startStationData = stationData.find(
|
||||
(station) => station.id.toString() === apiStore.context?.startStopId
|
||||
);
|
||||
@@ -1038,7 +991,6 @@ export const WebGLMap = observer(() => {
|
||||
|
||||
const terminalStations: number[] = [];
|
||||
|
||||
// Transform start station coordinates if found
|
||||
if (startStationData) {
|
||||
const startLocal = coordinatesToLocal(
|
||||
startStationData.latitude - centerLat,
|
||||
@@ -1051,7 +1003,6 @@ export const WebGLMap = observer(() => {
|
||||
terminalStations.push(startRx, startRy);
|
||||
}
|
||||
|
||||
// Transform end station coordinates if found
|
||||
if (endStationData) {
|
||||
const endLocal = coordinatesToLocal(
|
||||
endStationData.latitude - centerLat,
|
||||
@@ -1065,12 +1016,10 @@ export const WebGLMap = observer(() => {
|
||||
}
|
||||
|
||||
if (terminalStations.length > 0) {
|
||||
// Determine if each terminal station is passed
|
||||
const terminalStationData: any[] = [];
|
||||
if (startStationData) terminalStationData.push(startStationData);
|
||||
if (endStationData) terminalStationData.push(endStationData);
|
||||
|
||||
// Get tram segment index for comparison
|
||||
let tramSegIndex = -1;
|
||||
const coords: any = apiStore?.context?.currentCoordinates;
|
||||
if (coords && centerLat !== undefined && centerLon !== undefined) {
|
||||
@@ -1085,7 +1034,6 @@ export const WebGLMap = observer(() => {
|
||||
const tx = wx * cosR - wy * sinR;
|
||||
const ty = wx * sinR + wy * cosR;
|
||||
|
||||
// Find closest segment to tram position
|
||||
let best = -1;
|
||||
let bestD = Infinity;
|
||||
for (let i = 0; i < routePath.length - 2; i += 2) {
|
||||
@@ -1110,7 +1058,6 @@ export const WebGLMap = observer(() => {
|
||||
tramSegIndex = best;
|
||||
}
|
||||
|
||||
// Check if each terminal station is passed
|
||||
const isStartPassed = startStationData
|
||||
? (() => {
|
||||
const sx = terminalStations[0];
|
||||
@@ -1186,46 +1133,41 @@ export const WebGLMap = observer(() => {
|
||||
gl.enableVertexAttribArray(a_pos_pts);
|
||||
gl.vertexAttribPointer(a_pos_pts, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
// Draw colored outline based on passed status - 24 pixels (x2)
|
||||
gl.uniform1f(u_pointSize, 18.0 * scale);
|
||||
if (startStationData && endStationData) {
|
||||
// Both stations - draw each with its own color
|
||||
if (isStartPassed) {
|
||||
gl.uniform4f(u_color_pts, 1.0, 0.4, 0.4, 1.0); // Ярко-красный для пройденных
|
||||
gl.uniform4f(u_color_pts, 1.0, 0.4, 0.4, 1.0);
|
||||
} else {
|
||||
gl.uniform4f(u_color_pts, 0.7, 0.7, 0.7, 1.0); // Светло-серый для непройденных
|
||||
gl.uniform4f(u_color_pts, 0.7, 0.7, 0.7, 1.0);
|
||||
}
|
||||
gl.drawArrays(gl.POINTS, 0, 1); // Draw start station
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
|
||||
if (isEndPassed) {
|
||||
gl.uniform4f(u_color_pts, 1.0, 0.4, 0.4, 1.0); // Ярко-красный для пройденных
|
||||
gl.uniform4f(u_color_pts, 1.0, 0.4, 0.4, 1.0);
|
||||
} else {
|
||||
gl.uniform4f(u_color_pts, 0.7, 0.7, 0.7, 1.0); // Светло-серый для непройденных
|
||||
gl.uniform4f(u_color_pts, 0.7, 0.7, 0.7, 1.0);
|
||||
}
|
||||
gl.drawArrays(gl.POINTS, 1, 1); // Draw end station
|
||||
gl.drawArrays(gl.POINTS, 1, 1);
|
||||
} else {
|
||||
// Single station - use appropriate color
|
||||
const isPassed = startStationData ? isStartPassed : isEndPassed;
|
||||
if (isPassed) {
|
||||
gl.uniform4f(u_color_pts, 1.0, 0.4, 0.4, 1.0); // Ярко-красный для пройденных
|
||||
gl.uniform4f(u_color_pts, 1.0, 0.4, 0.4, 1.0);
|
||||
} else {
|
||||
gl.uniform4f(u_color_pts, 0.7, 0.7, 0.7, 1.0); // Светло-серый для непройденных
|
||||
gl.uniform4f(u_color_pts, 0.7, 0.7, 0.7, 1.0);
|
||||
}
|
||||
gl.drawArrays(gl.POINTS, 0, terminalStations.length / 2);
|
||||
}
|
||||
|
||||
// Draw dark center - 12 pixels (x2)
|
||||
gl.uniform1f(u_pointSize, 11.0 * scale);
|
||||
const r_center = ((BACKGROUND_COLOR >> 16) & 0xff) / 255;
|
||||
const g_center = ((BACKGROUND_COLOR >> 8) & 0xff) / 255;
|
||||
const b_center = (BACKGROUND_COLOR & 0xff) / 255;
|
||||
gl.uniform4f(u_color_pts, r_center, g_center, b_center, 1.0); // Dark color
|
||||
gl.uniform4f(u_color_pts, r_center, g_center, b_center, 1.0);
|
||||
gl.drawArrays(gl.POINTS, 0, terminalStations.length / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw yellow dot for tram position
|
||||
if (animatedYellowDotPosition) {
|
||||
const rx = animatedYellowDotPosition.x;
|
||||
const ry = animatedYellowDotPosition.y;
|
||||
@@ -1327,7 +1269,6 @@ export const WebGLMap = observer(() => {
|
||||
});
|
||||
|
||||
const onPointerDown = (e: PointerEvent) => {
|
||||
// Отслеживаем активность пользователя
|
||||
updateUserActivity();
|
||||
if (isAutoMode) {
|
||||
setIsAutoMode(false);
|
||||
@@ -1360,7 +1301,6 @@ export const WebGLMap = observer(() => {
|
||||
const onPointerMove = (e: PointerEvent) => {
|
||||
if (!activePointers.has(e.pointerId)) return;
|
||||
|
||||
// Отслеживаем активность пользователя
|
||||
updateUserActivity();
|
||||
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
@@ -1386,7 +1326,6 @@ export const WebGLMap = observer(() => {
|
||||
};
|
||||
}
|
||||
|
||||
// Process the pinch gesture
|
||||
if (pinchStart) {
|
||||
const currentDistance = getDistance(p1, p2);
|
||||
const zoomFactor = currentDistance / pinchStart.distance;
|
||||
@@ -1405,7 +1344,6 @@ export const WebGLMap = observer(() => {
|
||||
} else if (isDragging && activePointers.size === 1) {
|
||||
const p = Array.from(activePointers.values())[0];
|
||||
|
||||
// Проверяем валидность значений
|
||||
if (
|
||||
!startMouse ||
|
||||
!startPos ||
|
||||
@@ -1433,7 +1371,6 @@ export const WebGLMap = observer(() => {
|
||||
};
|
||||
|
||||
const onPointerUp = (e: PointerEvent) => {
|
||||
// Отслеживаем активность пользователя
|
||||
updateUserActivity();
|
||||
|
||||
canvas.releasePointerCapture(e.pointerId);
|
||||
@@ -1453,7 +1390,6 @@ export const WebGLMap = observer(() => {
|
||||
};
|
||||
|
||||
const onPointerCancel = (e: PointerEvent) => {
|
||||
// Handle pointer cancellation (e.g., when touch is interrupted)
|
||||
updateUserActivity();
|
||||
canvas.releasePointerCapture(e.pointerId);
|
||||
activePointers.delete(e.pointerId);
|
||||
@@ -1467,7 +1403,6 @@ export const WebGLMap = observer(() => {
|
||||
const onWheel = (e: WheelEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
// Отслеживаем активность пользователя
|
||||
updateUserActivity();
|
||||
if (isAutoMode) {
|
||||
setIsAutoMode(false);
|
||||
@@ -1475,7 +1410,6 @@ export const WebGLMap = observer(() => {
|
||||
cameraAnimationStore.stopAnimation();
|
||||
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
// Convert mouse coordinates from CSS pixels to physical canvas pixels
|
||||
const mouseX =
|
||||
(e.clientX - rect.left) * (canvas.width / canvas.clientWidth);
|
||||
const mouseY =
|
||||
@@ -1582,7 +1516,6 @@ export const WebGLMap = observer(() => {
|
||||
const sy = (ry * scale + position.y) / dpr;
|
||||
const size = 30;
|
||||
|
||||
// Обработчик клика для выбора достопримечательности
|
||||
const handleSightClick = () => {
|
||||
const {
|
||||
setSelectedSightId,
|
||||
|
||||
Reference in New Issue
Block a user