Auto-fit text objects in editor
This commit is contained in:
@@ -120,6 +120,27 @@ function wrapCanvasText(text, maxWidthPx) {
|
|||||||
return lines.length ? lines : [""];
|
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) {
|
function objectContentEndMm(obj) {
|
||||||
if (obj.hidden) return 0;
|
if (obj.hidden) return 0;
|
||||||
if (state.design.orientation === "portrait") return obj.y + obj.h;
|
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;
|
state.design.orientation = document.querySelector("input[name='orientation']:checked").value;
|
||||||
controls.lengthMm.disabled = state.design.autoLength;
|
controls.lengthMm.disabled = state.design.autoLength;
|
||||||
if (state.design.autoLength) {
|
if (state.design.autoLength) {
|
||||||
|
autoFitTextObjects();
|
||||||
state.design.lengthMm = contentLengthMm();
|
state.design.lengthMm = contentLengthMm();
|
||||||
controls.lengthMm.value = state.design.lengthMm;
|
controls.lengthMm.value = state.design.lengthMm;
|
||||||
}
|
}
|
||||||
@@ -361,6 +383,7 @@ function addObject(type, data = {}) {
|
|||||||
cols: 2,
|
cols: 2,
|
||||||
...data,
|
...data,
|
||||||
};
|
};
|
||||||
|
autoFitTextObject(base);
|
||||||
state.design.objects.push(base);
|
state.design.objects.push(base);
|
||||||
state.selectedId = base.id;
|
state.selectedId = base.id;
|
||||||
draw();
|
draw();
|
||||||
@@ -401,11 +424,13 @@ function updateProps() {
|
|||||||
function applyProps() {
|
function applyProps() {
|
||||||
const obj = selected();
|
const obj = selected();
|
||||||
if (!obj) return;
|
if (!obj) return;
|
||||||
|
const manuallySizing = document.activeElement === controls.propW || document.activeElement === controls.propH;
|
||||||
obj.text = controls.propText.value;
|
obj.text = controls.propText.value;
|
||||||
obj.x = Number(controls.propX.value);
|
obj.x = Number(controls.propX.value);
|
||||||
obj.y = Number(controls.propY.value);
|
obj.y = Number(controls.propY.value);
|
||||||
obj.w = Number(controls.propW.value);
|
obj.w = Number(controls.propW.value);
|
||||||
obj.h = Number(controls.propH.value);
|
obj.h = Number(controls.propH.value);
|
||||||
|
if (manuallySizing) obj.manualSize = true;
|
||||||
obj.fontSizeMm = Number(controls.propFont.value);
|
obj.fontSizeMm = Number(controls.propFont.value);
|
||||||
obj.lineMm = Number(controls.propLine.value);
|
obj.lineMm = Number(controls.propLine.value);
|
||||||
obj.align = controls.propAlign.value;
|
obj.align = controls.propAlign.value;
|
||||||
@@ -413,6 +438,7 @@ function applyProps() {
|
|||||||
obj.fill = controls.propFill.checked;
|
obj.fill = controls.propFill.checked;
|
||||||
obj.rows = Number(controls.propRows.value);
|
obj.rows = Number(controls.propRows.value);
|
||||||
obj.cols = Number(controls.propCols.value);
|
obj.cols = Number(controls.propCols.value);
|
||||||
|
autoFitTextObject(obj);
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,6 +519,7 @@ window.addEventListener("mousemove", (event) => {
|
|||||||
if (state.dragging.resize) {
|
if (state.dragging.resize) {
|
||||||
obj.w = Math.max(2, point.x - obj.x);
|
obj.w = Math.max(2, point.x - obj.x);
|
||||||
obj.h = Math.max(2, point.y - obj.y);
|
obj.h = Math.max(2, point.y - obj.y);
|
||||||
|
obj.manualSize = true;
|
||||||
} else {
|
} else {
|
||||||
obj.x = Math.max(0, point.x - state.dragging.dx);
|
obj.x = Math.max(0, point.x - state.dragging.dx);
|
||||||
obj.y = Math.max(0, point.y - state.dragging.dy);
|
obj.y = Math.max(0, point.y - state.dragging.dy);
|
||||||
|
|||||||
Reference in New Issue
Block a user