style: 合并断点线路展示并改为直角线段

This commit is contained in:
2026-07-17 01:13:10 +08:00
parent 77b487c326
commit 234e22468a
+41 -50
View File
@@ -159,7 +159,7 @@
const bg = isActive ? li.color : '#f8fafc';
const fg = isActive ? getContrastColor(li.color) : '#334155';
const border = isActive ? li.color : '#cbd5e1';
html += `<button class="tvm-line-btn" style="padding: 6px 12px; border: 1.5px solid ${border}; background: ${bg}; color: ${fg}; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 13px; transition: all 0.25s ease;" onclick="selectTvmLine(${i})">${li.name}</button>`;
html += `<button class="tvm-line-btn" style="padding: 6px 12px; border: 1.5px solid ${border}; background: ${bg}; color: ${fg}; border-radius: 0; cursor: pointer; font-weight: bold; font-size: 13px; transition: all 0.25s ease;" onclick="selectTvmLine(${i})">${li.name}</button>`;
}
container.innerHTML = html;
}
@@ -181,14 +181,30 @@
const startX = 40;
const gapX = 65;
const breakGapX = 36;
const y = 60;
const pts = [];
const lineSegments = [];
let currentSegment = [];
let cursorX = startX;
for (let i = 0; i < li.stops.length; i++) {
const code = li.stops[i];
if (code === '-') continue;
const x = startX + pts.length * gapX;
pts.push({ x, y, code });
if (code === '-') {
if (currentSegment.length > 0) {
lineSegments.push(currentSegment);
currentSegment = [];
}
cursorX += breakGapX;
continue;
}
const point = { x: cursorX, y, code };
pts.push(point);
currentSegment.push(point);
cursorX += gapX;
}
if (currentSegment.length > 0) {
lineSegments.push(currentSegment);
}
if (pts.length === 0) {
@@ -198,17 +214,18 @@
let svgContent = '';
if (pts.length >= 2) {
let d = `M ${pts[0].x} ${y}`;
for(let i=1; i<pts.length; i++) d += ` L ${pts[i].x} ${y}`;
svgContent += `<path d="${d}" fill="none" stroke="${li.color}" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" />`;
for (const segment of lineSegments) {
if (segment.length < 2) continue;
let d = `M ${segment[0].x} ${y}`;
for (let i = 1; i < segment.length; i++) d += ` L ${segment[i].x} ${y}`;
svgContent += `<path d="${d}" fill="none" stroke="${li.color}" stroke-width="6" stroke-linecap="butt" stroke-linejoin="miter" />`;
}
for (let i = 0; i < pts.length; i++) {
svgContent += renderStationNode(pts[i].x, pts[i].y, pts[i].code, i, li.color);
}
const width = Math.max(container.clientWidth || 800, startX + pts.length * gapX + 40);
const width = Math.max(container.clientWidth || 800, cursorX);
const height = 120;
// 添加 tvm-animate 类实现动画过渡
container.innerHTML = `<svg class="tvm-animate" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" style="display:block;">${svgContent}</svg>`;
@@ -266,7 +283,7 @@
}
for (const seg of segments) {
svgContent += `<line x1="${seg.x1}" y1="${y}" x2="${seg.x2}" y2="${y}" stroke="${seg.color}" stroke-width="6" stroke-linecap="round" />`;
svgContent += `<line x1="${seg.x1}" y1="${y}" x2="${seg.x2}" y2="${y}" stroke="${seg.color}" stroke-width="6" stroke-linecap="butt" />`;
}
const pathD = `M ${startX} ${y} L ${startX + (routeCodes.length - 1) * gapX} ${y}`;
@@ -278,7 +295,7 @@
for (let i = 0; i < numArrows; i++) {
svgContent += `
<g>
<path d="M -5 -4 L 3 0 L -5 4" fill="none" stroke="#854d0e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path d="M -5 -4 L 3 0 L -5 4" fill="none" stroke="#854d0e" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter" />
<animateMotion dur="${duration}s" repeatCount="indefinite" path="${pathD}" rotate="auto" begin="-${i * interval}s" calcMode="linear" />
</g>
`;
@@ -333,45 +350,19 @@
const stopsRaw = Array.isArray(line.stops) ? line.stops : (Array.isArray(line.站点列表) ? line.站点列表 : []);
const stops = stopsRaw.map(c => String(c || '').trim()).filter(Boolean);
if (stops.length === 0) continue;
let currentSegment = [];
let addedAny = false;
for (const c of stops) {
if (c === '-') {
if (currentSegment.length > 0) {
lineStops.push({ idx: currentLineIdx, name: line.name || line.线路名称 || '', enName: line.en_name || line.英文名称 || line.英文名 || '', color, stops: currentSegment });
lineColors.push(color);
for (const stopCode of currentSegment) {
const arr = linesByStation.get(stopCode) || [];
arr.push(currentLineIdx);
linesByStation.set(stopCode, arr);
const canonical = stationCanonicalByCode[stopCode] || stopCode;
if (!lineIdxsByCanonical[canonical]) lineIdxsByCanonical[canonical] = new Set();
lineIdxsByCanonical[canonical].add(currentLineIdx);
}
currentSegment = [];
addedAny = true;
}
} else {
currentSegment.push(c);
}
}
if (currentSegment.length > 0) {
lineStops.push({ idx: currentLineIdx, name: line.name || line.线路名称 || '', enName: line.en_name || line.英文名称 || line.英文名 || '', color, stops: currentSegment });
lineColors.push(color);
for (const stopCode of currentSegment) {
const arr = linesByStation.get(stopCode) || [];
arr.push(currentLineIdx);
linesByStation.set(stopCode, arr);
const canonical = stationCanonicalByCode[stopCode] || stopCode;
if (!lineIdxsByCanonical[canonical]) lineIdxsByCanonical[canonical] = new Set();
lineIdxsByCanonical[canonical].add(currentLineIdx);
}
addedAny = true;
}
if (addedAny) {
currentLineIdx++;
const stopCodes = stops.filter(stopCode => stopCode !== '-');
if (stopCodes.length === 0) continue;
lineStops.push({ idx: currentLineIdx, name: line.name || line.线路名称 || '', enName: line.en_name || line.英文名称 || line.英文名 || '', color, stops });
lineColors.push(color);
for (const stopCode of stopCodes) {
const arr = linesByStation.get(stopCode) || [];
arr.push(currentLineIdx);
linesByStation.set(stopCode, arr);
const canonical = stationCanonicalByCode[stopCode] || stopCode;
if (!lineIdxsByCanonical[canonical]) lineIdxsByCanonical[canonical] = new Set();
lineIdxsByCanonical[canonical].add(currentLineIdx);
}
currentLineIdx++;
}
if (lineStops.length === 0) {
@@ -392,7 +383,7 @@
.tvm-animate { animation: tvmFadeIn 0.3s ease-out forwards; }
.tvm-scroll-container { scroll-behavior: smooth; -webkit-overflow-scrolling: touch; }
.tvm-scroll-container::-webkit-scrollbar { height: 4px; }
.tvm-scroll-container::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 2px; }
.tvm-scroll-container::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 0; }
.tvm-scroll-container::-webkit-scrollbar-track { background: transparent; }
</style>`;