auto width

This commit is contained in:
Robin Appelman 2025-10-06 21:54:21 +02:00
commit 9073a9d217
3 changed files with 52 additions and 16 deletions

View file

@ -31,9 +31,13 @@
<label for="canvas-width">Width</label>
<input type="number" min="0" id="canvas-width" value="300">
<select id="canvas-width-unit">
<option value="px" selected>px</option>
<option value="px">px</option>
<option value="mm">mm</option>
<option value="auto" selected="selected">Auto</option>
</select>
<span id="autoHelp">
Note: only left aligned elements are taking into account for determining the width.
</span>
</p>
<div id='tape'>
<canvas id="preview" height="32" width="300"></canvas>

View file

@ -10,6 +10,7 @@ const addImageButton = document.getElementById('add-image');
const printButton = document.getElementById('print');
const widthInput = document.getElementById('canvas-width');
const widthUnit = document.getElementById('canvas-width-unit');
const autoHelp = document.getElementById('autoHelp');
let tapeWidthMM = 0;
let defaultFontSize = 24;
@ -215,23 +216,29 @@ const getElements = () => {
let rows = elementsTableBody.getElementsByTagName('tr');
let elements = [];
for (let row of rows) {
let size = parseInt(row.querySelector('.size input').value, 10);
let x = parseInt(row.querySelector('.pos_x').value, 10);
let y = parseInt(row.querySelector('.pos_y').value, 10);
let base = row.querySelector('.pos_base').value;
if (row.dataset.type === 'text') {
let text = row.querySelector('.text input').value;
elements.push({
type: 'text',
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),
base: row.querySelector('.pos_base').value,
text, size, x, y, base,
width: (renderCtx) => {
renderCtx.font = `${size}px serif`;
let textSize = renderCtx.measureText(text);
return textSize.width;
}
});
} else if (row.dataset.type === 'image') {
let image = row.getElementsByTagName('img')[0];
let ratio = image.naturalWidth / image.naturalHeight;
let width = size * ratio;
elements.push({
type: 'image',
image: row.getElementsByTagName('img')[0],
size: parseInt(row.querySelector('.size input').value, 10),
x: parseInt(row.querySelector('.pos_x').value, 10),
y: parseInt(row.querySelector('.pos_y').value, 10),
base: row.querySelector('.pos_base').value,
image, size, x, y, base,
width: (_renderCtx) => width,
});
}
}
@ -240,6 +247,15 @@ const getElements = () => {
const render = () => {
let elements = getElements();
if (widthUnit.value === "auto") {
let autoWidth = 20;
for (let element of elements) {
if (element.base === 'left') {
autoWidth = Math.max(autoWidth, element.x + element.width(renderCtx));
}
}
preview.width = autoWidth;
}
let width = preview.width;
let height = preview.height;
renderCtx.filter = '';
@ -248,19 +264,18 @@ const render = () => {
renderCtx.fillStyle = textColor;
for (let element of elements) {
let width = element.width(renderCtx);
if (element.type === 'text') {
renderCtx.filter = '';
renderCtx.font = `${element.size}px serif`;
let textSize = renderCtx.measureText(element.text);
let textHeight = textSize.fontBoundingBoxAscent - textSize.emHeightDescent;
renderCtx.fillText(element.text, calcX(element.base, element.x, textSize.width), element.y + textHeight);
renderCtx.fillText(element.text, calcX(element.base, element.x, width), element.y + textHeight);
} else if (element.type === 'image' && element.image.naturalWidth > 0) {
renderCtx.filter = 'grayscale() saturate(0%) brightness(70%) contrast(1000%)';
if (textColor === 'white') {
renderCtx.filter = renderCtx.filter + ' invert()';
}
let ratio = element.image.naturalWidth / element.image.naturalHeight;
let width = element.size * ratio;
renderCtx.drawImage(element.image, calcX(element.base, element.x, width), element.y, width, element.size);
}
}
@ -268,7 +283,6 @@ const render = () => {
const calcX = (base, x, width) => {
let imageWidth = preview.width;
console.log(base, x, width, imageWidth);
switch (base) {
case 'left':
return x;
@ -313,10 +327,21 @@ widthUnit.addEventListener('change', () => {
const pxPerMM = preview.height / tapeWidthMM;
if (widthUnit.value === "mm") {
widthInput.value = (preview.width / pxPerMM).toFixed(0);
} else {
widthInput.disabled = null;
widthInput.hidden = false;
autoHelp.classList.remove('show');
} else if (widthUnit.value === "px") {
widthInput.value = preview.width;
widthInput.hidden = false;
widthInput.disabled = null;
autoHelp.classList.remove('show');
} else {
widthInput.disabled = "disabled";
widthInput.hidden = true;
autoHelp.classList.add('show');
}
});
widthUnit.dispatchEvent(new Event('change'));
const apiRoot = "";

View file

@ -86,4 +86,11 @@ input {
display: inline-block;
width: auto;
background: var(--margin-color);
}
#autoHelp {
display: none;
&.show {
display: inline;
}
}