initial webui work

This commit is contained in:
Robin Appelman 2025-10-06 21:34:56 +02:00
commit 71cf4dbcb2
4 changed files with 248 additions and 4 deletions

156
web/label.js Normal file
View file

@ -0,0 +1,156 @@
const elementsTable = document.getElementById('elements');
/** @type HTMLCanvasElement preview */
const preview = document.getElementById('preview');
const renderCtx = preview.getContext("2d");
const elementsTableBody = elementsTable.getElementsByTagName('tbody')[0];
const addButton = document.getElementById('add');
const widthInput = document.getElementById('canvas-width');
const widthUnit = document.getElementById('canvas-width-unit');
let tapeWidthMM = 0;
let defaultFontSize = 24;
let backgroundColor = "white";
let textColor = "white";
const nextElementId = () => {
let rows = elementsTableBody.getElementsByTagName('tr');
if (rows.length === 0) {
return 1;
} else {
return parseInt(rows[0].dataset.elementId, 10) + 1;
}
};
const addElement = () => {
let id = nextElementId();
let row = document.createElement('tr');
row.dataset.elementId = id;
let textCol = document.createElement('td');
textCol.classList.add('text');
let textInput = document.createElement('input');
textInput.type = "text";
textInput.addEventListener('input', render);
textCol.appendChild(textInput);
row.appendChild(textCol);
{
let sizeCol = document.createElement('td');
sizeCol.classList.add('size');
let sizeInput = document.createElement('input');
sizeInput.addEventListener('input', render);
sizeInput.type = "number";
sizeInput.value = defaultFontSize.toString();
sizeCol.appendChild(document.createTextNode("Front size"))
sizeCol.appendChild(sizeInput);
row.appendChild(sizeCol);
}
{
let posCol = document.createElement('td');
posCol.classList.add('pos');
let posInputX = document.createElement('input');
posInputX.addEventListener('input', render);
posInputX.type = "number";
posInputX.value = "2";
posInputX.classList.add('pos_x');
let posInputY = document.createElement('input');
posInputY.addEventListener('input', render);
posInputY.type = "number";
posInputY.value = "2";
posInputY.classList.add('pos_y');
posCol.appendChild(document.createTextNode("Position"))
posCol.appendChild(posInputX);
posCol.appendChild(posInputY);
row.appendChild(posCol);
}
{
let removeCol = document.createElement('td');
removeCol.classList.add('delete');
let removeInput = document.createElement('input');
removeInput.type = "button";
removeInput.value = "×";
removeInput.addEventListener('click', removeElement);
removeCol.appendChild(removeInput);
row.appendChild(removeCol);
}
elementsTableBody.appendChild(row);
textInput.focus();
};
const removeElement = (event) => {
let row = event.target.parentElement.parentElement;
row.remove();
render();
};
const getElements = () => {
let rows = elementsTableBody.getElementsByTagName('tr');
let elements = [];
for (let row of rows) {
elements.push({
text: row.querySelector('.text input').value,
size: parseInt(row.querySelector('.size input').value, 10),
x: parseInt(row.querySelector('.pos_x').value, 10),
y: parseInt(row.querySelector('.pos_y').value, 10),
});
}
return elements;
}
const render = () => {
let elements = getElements();
let width = preview.width;
let height = preview.height;
renderCtx.fillStyle = backgroundColor;
renderCtx.fillRect(0, 0, width, height);
renderCtx.fillStyle = textColor;
for (let element of elements) {
renderCtx.font = `${element.size}px serif`;
renderCtx.fillText(element.text, element.x, height - element.y);
}
}
const resize = () => {
let width = parseInt(widthInput.value, 10);
const pxPerMM = preview.height / tapeWidthMM;
if (widthUnit.value === "mm") {
preview.width = width * pxPerMM;
} else {
preview.width = width;
}
render()
};
addButton.addEventListener('click', addElement);
widthInput.addEventListener('input', resize);
widthUnit.addEventListener('change', () => {
const pxPerMM = preview.height / tapeWidthMM;
if (widthUnit.value === "mm") {
widthInput.value = (preview.width / pxPerMM).toFixed(0);
} else {
widthInput.value = preview.width;
}
});
const apiRoot = "";
fetch(apiRoot + '/status')
.then(res => res.json())
/** @param {{pixel_width: number, media_width: number, margin_width: number, tape_color: string, text_color: string}} status */
.then(status => {
preview.height = status.pixel_width;
defaultFontSize = status.pixel_width;
backgroundColor = status.tape_color;
textColor = status.text_color;
tapeWidthMM = status.media_width;
render();
addElement();
})