feat(购票页): 添加动态路线箭头并优化代码格式
新增沿路线循环移动的动态指示箭头,自动适配路线总长度计算动画参数;修复文件开头多余的零宽空格,统一renderRouteOverlay函数内的代码缩进。
This commit is contained in:
+38
-2
@@ -1,4 +1,4 @@
|
|||||||
(() => {
|
(() => {
|
||||||
const $ = (sel) => document.querySelector(sel);
|
const $ = (sel) => document.querySelector(sel);
|
||||||
const fromEl = $('#from');
|
const fromEl = $('#from');
|
||||||
const toEl = $('#to');
|
const toEl = $('#to');
|
||||||
@@ -474,10 +474,46 @@
|
|||||||
group.appendChild(glow);
|
group.appendChild(glow);
|
||||||
group.appendChild(main);
|
group.appendChild(main);
|
||||||
|
|
||||||
|
// Dynamic arrows pointing to the destination
|
||||||
|
let totalDist = 0;
|
||||||
|
for (let i = 0; i < points.length - 1; i++) {
|
||||||
|
const dx = points[i+1].x - points[i].x;
|
||||||
|
const dy = points[i+1].y - points[i].y;
|
||||||
|
totalDist += Math.sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
const speed = 100; // pixels per second
|
||||||
|
const duration = Math.max(1, totalDist / speed);
|
||||||
|
const numArrows = Math.max(1, Math.floor(duration / 0.7)); // one arrow approx every 0.7s
|
||||||
|
const interval = duration / numArrows;
|
||||||
|
|
||||||
|
for (let i = 0; i < numArrows; i++) {
|
||||||
|
const arrowG = document.createElementNS(ns, 'g');
|
||||||
|
const arrowPath = document.createElementNS(ns, 'path');
|
||||||
|
// Chevron shape
|
||||||
|
arrowPath.setAttribute('d', 'M -6 -5 L 4 0 L -6 5');
|
||||||
|
arrowPath.setAttribute('fill', 'none');
|
||||||
|
arrowPath.setAttribute('stroke', '#854d0e'); // Dark brown/orange to contrast with yellow
|
||||||
|
arrowPath.setAttribute('stroke-width', '2.5');
|
||||||
|
arrowPath.setAttribute('stroke-linecap', 'round');
|
||||||
|
arrowPath.setAttribute('stroke-linejoin', 'round');
|
||||||
|
|
||||||
|
const animateMotion = document.createElementNS(ns, 'animateMotion');
|
||||||
|
animateMotion.setAttribute('dur', `${duration}s`);
|
||||||
|
animateMotion.setAttribute('repeatCount', 'indefinite');
|
||||||
|
animateMotion.setAttribute('path', pathData);
|
||||||
|
animateMotion.setAttribute('rotate', 'auto');
|
||||||
|
animateMotion.setAttribute('begin', `-${i * interval}s`);
|
||||||
|
|
||||||
|
arrowG.appendChild(arrowPath);
|
||||||
|
arrowG.appendChild(animateMotion);
|
||||||
|
group.appendChild(arrowG);
|
||||||
|
}
|
||||||
|
|
||||||
const firstStation = svgEl.querySelector('.map-station');
|
const firstStation = svgEl.querySelector('.map-station');
|
||||||
if (firstStation) svgEl.insertBefore(group, firstStation);
|
if (firstStation) svgEl.insertBefore(group, firstStation);
|
||||||
else svgEl.appendChild(group);
|
else svgEl.appendChild(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSelectionUI(skipPreview = false) {
|
function updateSelectionUI(skipPreview = false) {
|
||||||
if (!(selection[0] && selection[1])) {
|
if (!(selection[0] && selection[1])) {
|
||||||
|
|||||||
Reference in New Issue
Block a user