Add mobile mode and print cut controls
This commit is contained in:
+44
-7
@@ -1,4 +1,12 @@
|
||||
const MM_TO_SCREEN = 6;
|
||||
const PRINTABLE_TAPE_PX = {
|
||||
3.5: 24,
|
||||
6: 32,
|
||||
9: 52,
|
||||
12: 76,
|
||||
18: 120,
|
||||
24: 128,
|
||||
};
|
||||
const STORAGE_KEY = "ptouch-web-layout";
|
||||
|
||||
const state = {
|
||||
@@ -10,6 +18,8 @@ const state = {
|
||||
lengthMm: 70,
|
||||
marginMm: 2,
|
||||
orientation: "landscape",
|
||||
cutMode: "auto",
|
||||
halfcut: "on",
|
||||
objects: [],
|
||||
},
|
||||
};
|
||||
@@ -22,6 +32,8 @@ const controls = {
|
||||
tapeWidth: document.getElementById("tapeWidth"),
|
||||
lengthMm: document.getElementById("lengthMm"),
|
||||
marginMm: document.getElementById("marginMm"),
|
||||
cutMode: document.getElementById("cutMode"),
|
||||
halfcut: document.getElementById("halfcut"),
|
||||
copies: document.getElementById("copies"),
|
||||
zoomLabel: document.getElementById("zoomLabel"),
|
||||
previewImage: document.getElementById("previewImage"),
|
||||
@@ -64,6 +76,11 @@ 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 selected() {
|
||||
return state.design.objects.find((obj) => obj.id === state.selectedId) || null;
|
||||
}
|
||||
@@ -77,6 +94,8 @@ function syncDesignControls() {
|
||||
state.design.tapeWidthMm = Number(controls.tapeWidth.value);
|
||||
state.design.lengthMm = Number(controls.lengthMm.value);
|
||||
state.design.marginMm = Number(controls.marginMm.value);
|
||||
state.design.cutMode = controls.cutMode.value;
|
||||
state.design.halfcut = controls.halfcut.value;
|
||||
state.design.orientation = document.querySelector("input[name='orientation']:checked").value;
|
||||
}
|
||||
|
||||
@@ -84,6 +103,8 @@ function applyDesignControls() {
|
||||
controls.tapeWidth.value = state.design.tapeWidthMm;
|
||||
controls.lengthMm.value = state.design.lengthMm;
|
||||
controls.marginMm.value = state.design.marginMm;
|
||||
controls.cutMode.value = state.design.cutMode || "auto";
|
||||
controls.halfcut.value = state.design.halfcut || "on";
|
||||
document.querySelector(`input[name='orientation'][value='${state.design.orientation}']`).checked = true;
|
||||
}
|
||||
|
||||
@@ -114,21 +135,25 @@ function drawRulers() {
|
||||
|
||||
function drawTextObject(obj) {
|
||||
ctx.save();
|
||||
ctx.fillStyle = "#000";
|
||||
ctx.font = `${obj.bold ? "700 " : ""}${mmToPx(obj.fontSizeMm || 5)}px system-ui, sans-serif`;
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.textAlign = obj.align || "left";
|
||||
const x = mmToPx(obj.x);
|
||||
const y = mmToPx(obj.y);
|
||||
const w = mmToPx(obj.w);
|
||||
const h = mmToPx(obj.h);
|
||||
ctx.beginPath();
|
||||
ctx.rect(x, y, w, h);
|
||||
ctx.clip();
|
||||
ctx.fillStyle = "#000";
|
||||
const fontPx = (obj.fontSizeMm || 5) * printablePxPerMm() * state.zoom;
|
||||
ctx.font = `${obj.bold ? "700 " : ""}${fontPx}px DejaVu Sans, Arial, system-ui, sans-serif`;
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.textAlign = obj.align || "left";
|
||||
const lines = String(obj.text || "").split("\n");
|
||||
const lineHeight = mmToPx((obj.fontSizeMm || 5) * 1.15);
|
||||
const lineHeight = fontPx * 1.15;
|
||||
const total = lineHeight * lines.length;
|
||||
let cy = y + h / 2 - total / 2 + lineHeight / 2;
|
||||
const tx = obj.align === "center" ? x + w / 2 : obj.align === "right" ? x + w : x;
|
||||
for (const line of lines) {
|
||||
ctx.fillText(line, tx, cy, w);
|
||||
ctx.fillText(line, tx, cy);
|
||||
cy += lineHeight;
|
||||
}
|
||||
ctx.restore();
|
||||
@@ -212,6 +237,18 @@ function draw() {
|
||||
ctx.setLineDash([]);
|
||||
|
||||
for (const obj of state.design.objects) drawObject(obj);
|
||||
|
||||
if (state.design.cutMode === "cutmark" || state.design.cutMode === "cutmark-chain") {
|
||||
ctx.strokeStyle = "#111";
|
||||
ctx.setLineDash([4, 4]);
|
||||
const x = canvas.width - mmToPx(1.5);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, 0);
|
||||
ctx.lineTo(x, canvas.height);
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
|
||||
drawRulers();
|
||||
controls.zoomLabel.textContent = `${Math.round(state.zoom * 100)}%`;
|
||||
updateProps();
|
||||
@@ -376,7 +413,7 @@ window.addEventListener("keydown", (event) => {
|
||||
}
|
||||
});
|
||||
|
||||
["tapeWidth", "lengthMm", "marginMm"].forEach((id) => document.getElementById(id).addEventListener("input", draw));
|
||||
["tapeWidth", "lengthMm", "marginMm", "cutMode", "halfcut"].forEach((id) => document.getElementById(id).addEventListener("input", draw));
|
||||
document.querySelectorAll("input[name='orientation']").forEach((input) => input.addEventListener("change", draw));
|
||||
Object.values(controls).forEach((control) => {
|
||||
if (control && control.id && control.id.startsWith("prop")) control.addEventListener("input", applyProps);
|
||||
|
||||
Reference in New Issue
Block a user