feat(web): 优化车站名与线路名显示,增加车站编号与英文名称

This commit is contained in:
2026-07-12 10:04:40 +08:00
parent 423a5972fc
commit 46f8a17157
4 changed files with 71 additions and 20 deletions
+67 -16
View File
@@ -215,7 +215,7 @@
for (const c of stops) {
if (c === '-') {
if (currentSegment.length > 0) {
lineStops.push({ idx: currentLineIdx, name: line.name || line.线路名称 || '', color, stops: currentSegment });
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) || [];
@@ -233,7 +233,7 @@
}
}
if (currentSegment.length > 0) {
lineStops.push({ idx: currentLineIdx, name: line.name || line.线路名称 || '', color, stops: currentSegment });
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) || [];
@@ -332,13 +332,15 @@
}
const labelPlacements = {};
const placeLabel = (x, y, isStart, name, color) => {
const placeLabel = (x, y, isStart, name, enName, color) => {
const key = `${x},${y},${isStart ? 'left' : 'right'}`;
const count = labelPlacements[key] || 0;
labelPlacements[key] = count + 1;
const nameLen = name.length * 13 + 16;
const yOffset = count * 30 - 12; // stack vertically, center on point initially
const hasEn = !!enName;
const nameLen = Math.max(name.length * 13 + 16, hasEn ? enName.length * 6.5 + 16 : 0);
const h = hasEn ? 36 : 24;
const yOffset = count * 42 - (h / 2);
let lx, textX;
if (isStart) {
@@ -349,8 +351,14 @@
textX = lx + nameLen / 2;
}
return `<rect x="${lx}" y="${y + yOffset}" width="${nameLen}" height="24" rx="12" fill="${color}" />` +
`<text x="${textX}" y="${y + yOffset + 16}" text-anchor="middle" fill="#fff" font-size="12" font-weight="bold">${name}</text>`;
let svg = `<rect x="${lx}" y="${y + yOffset}" width="${nameLen}" height="${h}" rx="6" fill="${color}" />`;
if (hasEn) {
svg += `<text x="${textX}" y="${y + yOffset + 15}" text-anchor="middle" fill="#fff" font-size="12" font-weight="bold">${name}</text>`;
svg += `<text x="${textX}" y="${y + yOffset + 28}" text-anchor="middle" fill="rgba(255,255,255,0.9)" font-size="9" font-weight="600">${enName}</text>`;
} else {
svg += `<text x="${textX}" y="${y + yOffset + 16}" text-anchor="middle" fill="#fff" font-size="12" font-weight="bold">${name}</text>`;
}
return svg;
};
let svgContent = '';
@@ -371,8 +379,8 @@
// Add line name labels at ends
const pStart = pts[0];
const pEnd = pts[pts.length - 1];
svgContent += placeLabel(pStart.x, pStart.y, true, li.name, li.color);
svgContent += placeLabel(pEnd.x, pEnd.y, false, li.name, li.color);
svgContent += placeLabel(pStart.x, pStart.y, true, li.name, li.enName, li.color);
svgContent += placeLabel(pEnd.x, pEnd.y, false, li.name, li.enName, li.color);
}
}
@@ -389,6 +397,9 @@
const isTransfer = uniqueColors.length >= 2 || codes.length >= 2;
const name = getStationDisplayName(primaryCode);
const enName = stationEnByCode[primaryCode] || '';
const showEn = !!enName;
let markerSvg = '';
if (isTransfer) {
markerSvg += `<circle cx="${x}" cy="${y}" r="15" fill="#ffffff" stroke="#1f2937" stroke-width="2.5" />`;
@@ -401,16 +412,56 @@
}
const preferTop = isTransfer || (i % 2 === 0 && y >= baseY + 20);
const labelY = preferTop ? (y - 22) : (y + 30);
const labelClass = preferTop ? 'station-label-top' : 'station-label-bottom';
let labelSvg = '';
if (isTransfer) {
const labelW = Math.max(72, name.length * 14 + 18);
labelSvg += `<rect x="${x - labelW / 2}" y="${labelY - 16}" width="${labelW}" height="24" rx="12" fill="rgba(248,250,252,0.96)" stroke="#cbd5e1" stroke-width="1.5" />`;
labelSvg += `<text class="${labelClass}" x="${x}" y="${labelY}" text-anchor="middle" fill="#334155" font-size="13" font-weight="800">${name}</text>`;
let textContent = '';
const codeFontSize = 9;
const nameFontSize = 13;
const enFontSize = 8.5;
const codeW = primaryCode.length * 6 + 10;
if (preferTop) {
const bottomY = y - 14;
const enY = bottomY;
const nameY = showEn ? bottomY - 12 : bottomY;
const codeY = nameY - 16;
if (isTransfer) {
const labelW = Math.max(72, name.length * 14 + 18, codeW + 16, showEn ? enName.length * 5.5 + 16 : 0);
const labelH = showEn ? 46 : 34;
const rectY = codeY - 10;
labelSvg += `<rect x="${x - labelW / 2}" y="${rectY}" width="${labelW}" height="${labelH}" rx="6" fill="rgba(255,255,255,0.95)" stroke="#cbd5e1" stroke-width="1.5" />`;
}
textContent += `<rect x="${x - codeW / 2}" y="${codeY - 8}" width="${codeW}" height="12" rx="3" fill="#f1f5f9" stroke="#cbd5e1" stroke-width="1" />`;
textContent += `<text x="${x}" y="${codeY + 1}" text-anchor="middle" fill="#475569" font-size="${codeFontSize}" font-weight="700" letter-spacing="0.02em">${primaryCode}</text>`;
textContent += `<text x="${x}" y="${nameY}" text-anchor="middle" fill="#334155" font-size="${nameFontSize}" font-weight="${isTransfer ? 800 : 700}">${name}</text>`;
if (showEn) {
textContent += `<text x="${x}" y="${enY}" text-anchor="middle" fill="#94a3b8" font-size="${enFontSize}" font-weight="600">${enName}</text>`;
}
} else {
labelSvg += `<text class="${labelClass}" x="${x}" y="${labelY}" text-anchor="middle" fill="#334155" font-size="13.5" font-weight="700">${name}</text>`;
const topY = y + 24;
const codeY = topY;
const nameY = topY + 16;
const enY = nameY + 12;
if (isTransfer) {
const labelW = Math.max(72, name.length * 14 + 18, codeW + 16, showEn ? enName.length * 5.5 + 16 : 0);
const labelH = showEn ? 46 : 34;
const rectY = codeY - 10;
labelSvg += `<rect x="${x - labelW / 2}" y="${rectY}" width="${labelW}" height="${labelH}" rx="6" fill="rgba(255,255,255,0.95)" stroke="#cbd5e1" stroke-width="1.5" />`;
}
textContent += `<rect x="${x - codeW / 2}" y="${codeY - 8}" width="${codeW}" height="12" rx="3" fill="#f1f5f9" stroke="#cbd5e1" stroke-width="1" />`;
textContent += `<text x="${x}" y="${codeY + 1}" text-anchor="middle" fill="#475569" font-size="${codeFontSize}" font-weight="700" letter-spacing="0.02em">${primaryCode}</text>`;
textContent += `<text x="${x}" y="${nameY}" text-anchor="middle" fill="#334155" font-size="${nameFontSize}" font-weight="${isTransfer ? 800 : 700}">${name}</text>`;
if (showEn) {
textContent += `<text x="${x}" y="${enY}" text-anchor="middle" fill="#94a3b8" font-size="${enFontSize}" font-weight="600">${enName}</text>`;
}
}
labelSvg += textContent;
svgContent += `
<g class="map-station ${isTransfer ? 'transfer' : ''}" data-code="${primaryCode}" data-canonical="${canonical}" onclick="handleStationClick('${primaryCode}')" style="cursor:pointer">