style: 合并断点线路展示并改为直角线段
This commit is contained in:
+41
-50
@@ -159,7 +159,7 @@
|
|||||||
const bg = isActive ? li.color : '#f8fafc';
|
const bg = isActive ? li.color : '#f8fafc';
|
||||||
const fg = isActive ? getContrastColor(li.color) : '#334155';
|
const fg = isActive ? getContrastColor(li.color) : '#334155';
|
||||||
const border = isActive ? li.color : '#cbd5e1';
|
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;
|
container.innerHTML = html;
|
||||||
}
|
}
|
||||||
@@ -181,14 +181,30 @@
|
|||||||
|
|
||||||
const startX = 40;
|
const startX = 40;
|
||||||
const gapX = 65;
|
const gapX = 65;
|
||||||
|
const breakGapX = 36;
|
||||||
const y = 60;
|
const y = 60;
|
||||||
const pts = [];
|
const pts = [];
|
||||||
|
const lineSegments = [];
|
||||||
|
let currentSegment = [];
|
||||||
|
let cursorX = startX;
|
||||||
|
|
||||||
for (let i = 0; i < li.stops.length; i++) {
|
for (let i = 0; i < li.stops.length; i++) {
|
||||||
const code = li.stops[i];
|
const code = li.stops[i];
|
||||||
if (code === '-') continue;
|
if (code === '-') {
|
||||||
const x = startX + pts.length * gapX;
|
if (currentSegment.length > 0) {
|
||||||
pts.push({ x, y, code });
|
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) {
|
if (pts.length === 0) {
|
||||||
@@ -198,17 +214,18 @@
|
|||||||
|
|
||||||
let svgContent = '';
|
let svgContent = '';
|
||||||
|
|
||||||
if (pts.length >= 2) {
|
for (const segment of lineSegments) {
|
||||||
let d = `M ${pts[0].x} ${y}`;
|
if (segment.length < 2) continue;
|
||||||
for(let i=1; i<pts.length; i++) d += ` L ${pts[i].x} ${y}`;
|
let d = `M ${segment[0].x} ${y}`;
|
||||||
svgContent += `<path d="${d}" fill="none" stroke="${li.color}" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" />`;
|
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++) {
|
for (let i = 0; i < pts.length; i++) {
|
||||||
svgContent += renderStationNode(pts[i].x, pts[i].y, pts[i].code, i, li.color);
|
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;
|
const height = 120;
|
||||||
// 添加 tvm-animate 类实现动画过渡
|
// 添加 tvm-animate 类实现动画过渡
|
||||||
container.innerHTML = `<svg class="tvm-animate" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" style="display:block;">${svgContent}</svg>`;
|
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) {
|
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}`;
|
const pathD = `M ${startX} ${y} L ${startX + (routeCodes.length - 1) * gapX} ${y}`;
|
||||||
@@ -278,7 +295,7 @@
|
|||||||
for (let i = 0; i < numArrows; i++) {
|
for (let i = 0; i < numArrows; i++) {
|
||||||
svgContent += `
|
svgContent += `
|
||||||
<g>
|
<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" />
|
<animateMotion dur="${duration}s" repeatCount="indefinite" path="${pathD}" rotate="auto" begin="-${i * interval}s" calcMode="linear" />
|
||||||
</g>
|
</g>
|
||||||
`;
|
`;
|
||||||
@@ -333,45 +350,19 @@
|
|||||||
const stopsRaw = Array.isArray(line.stops) ? line.stops : (Array.isArray(line.站点列表) ? line.站点列表 : []);
|
const stopsRaw = Array.isArray(line.stops) ? line.stops : (Array.isArray(line.站点列表) ? line.站点列表 : []);
|
||||||
const stops = stopsRaw.map(c => String(c || '').trim()).filter(Boolean);
|
const stops = stopsRaw.map(c => String(c || '').trim()).filter(Boolean);
|
||||||
if (stops.length === 0) continue;
|
if (stops.length === 0) continue;
|
||||||
|
const stopCodes = stops.filter(stopCode => stopCode !== '-');
|
||||||
let currentSegment = [];
|
if (stopCodes.length === 0) continue;
|
||||||
let addedAny = false;
|
lineStops.push({ idx: currentLineIdx, name: line.name || line.线路名称 || '', enName: line.en_name || line.英文名称 || line.英文名 || '', color, stops });
|
||||||
for (const c of stops) {
|
lineColors.push(color);
|
||||||
if (c === '-') {
|
for (const stopCode of stopCodes) {
|
||||||
if (currentSegment.length > 0) {
|
const arr = linesByStation.get(stopCode) || [];
|
||||||
lineStops.push({ idx: currentLineIdx, name: line.name || line.线路名称 || '', enName: line.en_name || line.英文名称 || line.英文名 || '', color, stops: currentSegment });
|
arr.push(currentLineIdx);
|
||||||
lineColors.push(color);
|
linesByStation.set(stopCode, arr);
|
||||||
for (const stopCode of currentSegment) {
|
const canonical = stationCanonicalByCode[stopCode] || stopCode;
|
||||||
const arr = linesByStation.get(stopCode) || [];
|
if (!lineIdxsByCanonical[canonical]) lineIdxsByCanonical[canonical] = new Set();
|
||||||
arr.push(currentLineIdx);
|
lineIdxsByCanonical[canonical].add(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++;
|
|
||||||
}
|
}
|
||||||
|
currentLineIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lineStops.length === 0) {
|
if (lineStops.length === 0) {
|
||||||
@@ -392,7 +383,7 @@
|
|||||||
.tvm-animate { animation: tvmFadeIn 0.3s ease-out forwards; }
|
.tvm-animate { animation: tvmFadeIn 0.3s ease-out forwards; }
|
||||||
.tvm-scroll-container { scroll-behavior: smooth; -webkit-overflow-scrolling: touch; }
|
.tvm-scroll-container { scroll-behavior: smooth; -webkit-overflow-scrolling: touch; }
|
||||||
.tvm-scroll-container::-webkit-scrollbar { height: 4px; }
|
.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; }
|
.tvm-scroll-container::-webkit-scrollbar-track { background: transparent; }
|
||||||
</style>`;
|
</style>`;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user