Align editor canvas text preview
This commit is contained in:
+47
-11
@@ -86,26 +86,62 @@ function pxToMm(v) {
|
||||
return v / scale();
|
||||
}
|
||||
|
||||
function printablePxPerMm() {
|
||||
const tape = Number(state.design.tapeWidthMm);
|
||||
return (PRINTABLE_TAPE_PX[tape] || (tape * 180) / 25.4) / tape;
|
||||
}
|
||||
|
||||
function inkColor() {
|
||||
return state.tapeInfo?.textColor?.css || "#000";
|
||||
}
|
||||
|
||||
function objectFont(obj) {
|
||||
const fontPx = mmToPx(obj.fontSizeMm || 5);
|
||||
return {
|
||||
size: fontPx,
|
||||
value: `${obj.bold ? "700 " : ""}${fontPx}px DejaVu Sans, Arial, system-ui, sans-serif`,
|
||||
};
|
||||
}
|
||||
|
||||
function clamp(value, min, max) {
|
||||
return Math.min(max, Math.max(min, value));
|
||||
}
|
||||
|
||||
function wrapCanvasText(text, maxWidthPx) {
|
||||
const lines = [];
|
||||
for (const rawLine of String(text || "").split("\n")) {
|
||||
let current = "";
|
||||
for (const word of rawLine.split(" ")) {
|
||||
const candidate = current ? `${current} ${word}` : word;
|
||||
if (ctx.measureText(candidate).width <= maxWidthPx) {
|
||||
current = candidate;
|
||||
continue;
|
||||
}
|
||||
if (current) lines.push(current);
|
||||
current = word;
|
||||
}
|
||||
lines.push(current);
|
||||
}
|
||||
return lines.length ? lines : [""];
|
||||
}
|
||||
|
||||
function objectContentEndMm(obj) {
|
||||
if (obj.hidden) return 0;
|
||||
if (state.design.orientation === "portrait") return obj.y + obj.h;
|
||||
if (obj.type !== "text" && obj.type !== "symbol") return obj.x + obj.w;
|
||||
|
||||
const { value } = objectFont(obj);
|
||||
ctx.save();
|
||||
ctx.font = value;
|
||||
const lines = wrapCanvasText(obj.text || "", mmToPx(obj.w));
|
||||
const textWidthMm = Math.max(...lines.map((line) => pxToMm(ctx.measureText(line).width)), 0);
|
||||
ctx.restore();
|
||||
|
||||
if (obj.align === "center") return obj.x + obj.w / 2 + textWidthMm / 2;
|
||||
if (obj.align === "right") return obj.x + obj.w;
|
||||
return obj.x + Math.min(obj.w, textWidthMm);
|
||||
}
|
||||
|
||||
function contentLengthMm() {
|
||||
if (!state.design.objects.length) return Number(controls.lengthMm.value) || state.design.lengthMm || 70;
|
||||
const margin = Number(controls.marginMm.value) || 0;
|
||||
const lengthEnd = state.design.objects.reduce((max, obj) => {
|
||||
if (obj.hidden) return max;
|
||||
const end = state.design.orientation === "portrait" ? obj.y + obj.h : obj.x + obj.w;
|
||||
return Math.max(max, end);
|
||||
return Math.max(max, objectContentEndMm(obj));
|
||||
}, margin);
|
||||
return Math.ceil(clamp(lengthEnd + margin, 10, 500));
|
||||
}
|
||||
@@ -193,11 +229,11 @@ function drawTextObject(obj) {
|
||||
ctx.rect(x, y, w, h);
|
||||
ctx.clip();
|
||||
ctx.fillStyle = inkColor();
|
||||
const fontPx = (obj.fontSizeMm || 5) * printablePxPerMm() * state.zoom;
|
||||
ctx.font = `${obj.bold ? "700 " : ""}${fontPx}px DejaVu Sans, Arial, system-ui, sans-serif`;
|
||||
const { size: fontPx, value: font } = objectFont(obj);
|
||||
ctx.font = font;
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.textAlign = obj.align || "left";
|
||||
const lines = String(obj.text || "").split("\n");
|
||||
const lines = wrapCanvasText(obj.text || "", w);
|
||||
const lineHeight = fontPx * 1.15;
|
||||
const total = lineHeight * lines.length;
|
||||
let cy = y + h / 2 - total / 2 + lineHeight / 2;
|
||||
|
||||
Reference in New Issue
Block a user