Auto-fit text objects in editor
This commit is contained in:
@@ -120,6 +120,27 @@ function wrapCanvasText(text, maxWidthPx) {
|
||||
return lines.length ? lines : [""];
|
||||
}
|
||||
|
||||
function textNaturalWidthMm(obj) {
|
||||
const { value } = objectFont(obj);
|
||||
ctx.save();
|
||||
ctx.font = value;
|
||||
const lines = String(obj.text || " ").split("\n");
|
||||
const maxTextWidthPx = Math.max(...lines.map((line) => ctx.measureText(line || " ").width), 0);
|
||||
ctx.restore();
|
||||
return Math.max(2, pxToMm(maxTextWidthPx) + 1);
|
||||
}
|
||||
|
||||
function autoFitTextObject(obj) {
|
||||
if (!state.design.autoLength || obj.manualSize || (obj.type !== "text" && obj.type !== "symbol")) return;
|
||||
const maxLength = state.design.orientation === "portrait" ? state.design.tapeWidthMm : 500;
|
||||
const available = Math.max(2, maxLength - obj.x - state.design.marginMm);
|
||||
obj.w = Math.min(available, textNaturalWidthMm(obj));
|
||||
}
|
||||
|
||||
function autoFitTextObjects() {
|
||||
for (const obj of state.design.objects) autoFitTextObject(obj);
|
||||
}
|
||||
|
||||
function objectContentEndMm(obj) {
|
||||
if (obj.hidden) return 0;
|
||||
if (state.design.orientation === "portrait") return obj.y + obj.h;
|
||||
@@ -180,6 +201,7 @@ function syncDesignControls() {
|
||||
state.design.orientation = document.querySelector("input[name='orientation']:checked").value;
|
||||
controls.lengthMm.disabled = state.design.autoLength;
|
||||
if (state.design.autoLength) {
|
||||
autoFitTextObjects();
|
||||
state.design.lengthMm = contentLengthMm();
|
||||
controls.lengthMm.value = state.design.lengthMm;
|
||||
}
|
||||
@@ -361,6 +383,7 @@ function addObject(type, data = {}) {
|
||||
cols: 2,
|
||||
...data,
|
||||
};
|
||||
autoFitTextObject(base);
|
||||
state.design.objects.push(base);
|
||||
state.selectedId = base.id;
|
||||
draw();
|
||||
@@ -401,11 +424,13 @@ function updateProps() {
|
||||
function applyProps() {
|
||||
const obj = selected();
|
||||
if (!obj) return;
|
||||
const manuallySizing = document.activeElement === controls.propW || document.activeElement === controls.propH;
|
||||
obj.text = controls.propText.value;
|
||||
obj.x = Number(controls.propX.value);
|
||||
obj.y = Number(controls.propY.value);
|
||||
obj.w = Number(controls.propW.value);
|
||||
obj.h = Number(controls.propH.value);
|
||||
if (manuallySizing) obj.manualSize = true;
|
||||
obj.fontSizeMm = Number(controls.propFont.value);
|
||||
obj.lineMm = Number(controls.propLine.value);
|
||||
obj.align = controls.propAlign.value;
|
||||
@@ -413,6 +438,7 @@ function applyProps() {
|
||||
obj.fill = controls.propFill.checked;
|
||||
obj.rows = Number(controls.propRows.value);
|
||||
obj.cols = Number(controls.propCols.value);
|
||||
autoFitTextObject(obj);
|
||||
draw();
|
||||
}
|
||||
|
||||
@@ -493,6 +519,7 @@ window.addEventListener("mousemove", (event) => {
|
||||
if (state.dragging.resize) {
|
||||
obj.w = Math.max(2, point.x - obj.x);
|
||||
obj.h = Math.max(2, point.y - obj.y);
|
||||
obj.manualSize = true;
|
||||
} else {
|
||||
obj.x = Math.max(0, point.x - state.dragging.dx);
|
||||
obj.y = Math.max(0, point.y - state.dragging.dy);
|
||||
|
||||
Reference in New Issue
Block a user