Fix SVG export label alignment for all conveyance types

- Curved: position at arc midpoint with rotation along curve
- Spur: center in trapezoid shape, not bounding box
- All: use dy offset instead of dominant-baseline for reliable centering

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
igurielidze 2026-03-30 20:31:00 +04:00
parent 896198c9d4
commit 6a38ecaa27

View File

@ -20,16 +20,52 @@ function parseConveyanceLabel(label: string): { lines: string[]; stripped: strin
/** Emit conveyance label text element inside the shape */
function emitConveyanceLabel(lines: string[], sym: PlacedSymbol, outerTransform: string) {
if (!sym.label) return;
const { lines: textLines } = parseConveyanceLabel(sym.label);
const cx = sym.x + sym.w / 2;
const cy = sym.y + sym.h / 2;
const fontSize = Math.min(14, (sym.h - 4) / textLines.length);
const { lines: textLines, stripped } = parseConveyanceLabel(sym.label);
const tAttr = outerTransform ? ` transform="${outerTransform}"` : '';
// Curved symbols: place along arc midpoint
if (isCurvedType(sym.symbolId)) {
const angle = sym.curveAngle || 90;
const { arcCx, arcCy, outerR, innerR, bandW } = getCurveGeometry(sym.symbolId, sym.x, sym.y, sym.w, sym.h);
const midR = (outerR + innerR) / 2;
const midAngleRad = ((angle / 2) * Math.PI) / 180;
const textX = arcCx + midR * Math.cos(midAngleRad);
const textY = arcCy - midR * Math.sin(midAngleRad);
const rotDeg = -angle / 2 + 90;
const fontSize = Math.min(14, (bandW - 4) / textLines.length);
if (fontSize < 4) return;
const lineH = fontSize;
const startY = cy - (textLines.length - 1) * lineH / 2;
const tAttr = outerTransform ? ` transform="${outerTransform}"` : '';
const curveTransform = `translate(${textX},${textY}) rotate(${rotDeg})${outerTransform ? ' ' + outerTransform : ''}`;
for (let i = 0; i < textLines.length; i++) {
lines.push(` <text x="${cx}" y="${startY + i * lineH}" text-anchor="middle" dominant-baseline="central" font-family="Arial" font-weight="bold" font-size="${fontSize}px" fill="#000000"${tAttr}>${textLines[i]}</text>`);
const dy = -(textLines.length - 1) * lineH / 2 + i * lineH;
lines.push(` <text x="0" y="0" dy="${dy + fontSize * 0.35}" text-anchor="middle" font-family="Arial" font-weight="bold" font-size="${fontSize}px" fill="#000000" transform="${curveTransform}">${textLines[i]}</text>`);
}
return;
}
// Spur: center in trapezoid
let labelCx: number, labelCy: number, availW: number, availH: number;
if (isSpurType(sym.symbolId)) {
const w2 = sym.w2 ?? sym.w;
const midW = (w2 + sym.w) / 2;
labelCx = sym.x + midW / 2;
labelCy = sym.y + sym.h / 2;
availW = midW - 4;
availH = sym.h - 4;
} else {
labelCx = sym.x + sym.w / 2;
labelCy = sym.y + sym.h / 2;
availW = sym.w - 4;
availH = sym.h - 4;
}
const useLines = textLines;
const fontSize = Math.min(14, availH / useLines.length);
if (fontSize < 4) return;
const lineH = fontSize;
for (let i = 0; i < useLines.length; i++) {
const dy = -(useLines.length - 1) * lineH / 2 + i * lineH;
lines.push(` <text x="${labelCx}" y="${labelCy + dy + fontSize * 0.35}" text-anchor="middle" font-family="Arial" font-weight="bold" font-size="${fontSize}px" fill="#000000"${tAttr}>${useLines[i]}</text>`);
}
}