style: 合并断点线路展示并改为直角线段
This commit is contained in:
+41
-50
@@ -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>`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user