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> <label for="canvas-width">Width</label>
<input type="number" min="0" id="canvas-width" value="300"> <input type="number" min="0" id="canvas-width" value="300">
<select id="canvas-width-unit"> <select id="canvas-width-unit">
<option value="px" selected>px</option> <option value="px">px</option>
<option value="mm">mm</option> <option value="mm">mm</option>
<option value="auto" selected="selected">Auto</option>
</select> </select>
<span id="autoHelp">
Note: only left aligned elements are taking into account for determining the width.
</span>
</p> </p>
<div id='tape'> <div id='tape'>
<canvas id="preview" height="32" width="300"></canvas> <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 printButton = document.getElementById('print');
const widthInput = document.getElementById('canvas-width'); const widthInput = document.getElementById('canvas-width');
const widthUnit = document.getElementById('canvas-width-unit'); const widthUnit = document.getElementById('canvas-width-unit');
const autoHelp = document.getElementById('autoHelp');
let tapeWidthMM = 0; let tapeWidthMM = 0;
let defaultFontSize = 24; let defaultFontSize = 24;
@ -215,23 +216,29 @@ const getElements = () => {
let rows = elementsTableBody.getElementsByTagName('tr'); let rows = elementsTableBody.getElementsByTagName('tr');
let elements = []; let elements = [];
for (let row of rows) { 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') { if (row.dataset.type === 'text') {
let text = row.querySelector('.text input').value;
elements.push({ elements.push({
type: 'text', type: 'text',
text: row.querySelector('.text input').value, text, size, x, y, base,
size: parseInt(row.querySelector('.size input').value, 10), width: (renderCtx) => {
x: parseInt(row.querySelector('.pos_x').value, 10), renderCtx.font = `${size}px serif`;
y: parseInt(row.querySelector('.pos_y').value, 10), let textSize = renderCtx.measureText(text);
base: row.querySelector('.pos_base').value, return textSize.width;
}
}); });
} else if (row.dataset.type === 'image') { } else if (row.dataset.type === 'image') {
let image = row.getElementsByTagName('img')[0];
let ratio = image.naturalWidth / image.naturalHeight;
let width = size * ratio;
elements.push({ elements.push({
type: 'image', type: 'image',
image: row.getElementsByTagName('img')[0], image, size, x, y, base,
size: parseInt(row.querySelector('.size input').value, 10), width: (_renderCtx) => width,
x: parseInt(row.querySelector('.pos_x').value, 10),
y: parseInt(row.querySelector('.pos_y').value, 10),
base: row.querySelector('.pos_base').value,
}); });
} }
} }
@ -240,6 +247,15 @@ const getElements = () => {
const render = () => { const render = () => {
let elements = getElements(); 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 width = preview.width;
let height = preview.height; let height = preview.height;
renderCtx.filter = ''; renderCtx.filter = '';
@ -248,19 +264,18 @@ const render = () => {
renderCtx.fillStyle = textColor; renderCtx.fillStyle = textColor;
for (let element of elements) { for (let element of elements) {
let width = element.width(renderCtx);
if (element.type === 'text') { if (element.type === 'text') {
renderCtx.filter = ''; renderCtx.filter = '';
renderCtx.font = `${element.size}px serif`; renderCtx.font = `${element.size}px serif`;
let textSize = renderCtx.measureText(element.text); let textSize = renderCtx.measureText(element.text);
let textHeight = textSize.fontBoundingBoxAscent - textSize.emHeightDescent; 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) { } else if (element.type === 'image' && element.image.naturalWidth > 0) {
renderCtx.filter = 'grayscale() saturate(0%) brightness(70%) contrast(1000%)'; renderCtx.filter = 'grayscale() saturate(0%) brightness(70%) contrast(1000%)';
if (textColor === 'white') { if (textColor === 'white') {
renderCtx.filter = renderCtx.filter + ' invert()'; 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); 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) => { const calcX = (base, x, width) => {
let imageWidth = preview.width; let imageWidth = preview.width;
console.log(base, x, width, imageWidth);
switch (base) { switch (base) {
case 'left': case 'left':
return x; return x;
@ -313,10 +327,21 @@ widthUnit.addEventListener('change', () => {
const pxPerMM = preview.height / tapeWidthMM; const pxPerMM = preview.height / tapeWidthMM;
if (widthUnit.value === "mm") { if (widthUnit.value === "mm") {
widthInput.value = (preview.width / pxPerMM).toFixed(0); 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.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 = ""; const apiRoot = "";

View file

@ -87,3 +87,10 @@ input {
width: auto; width: auto;
background: var(--margin-color); background: var(--margin-color);
} }
#autoHelp {
display: none;
&.show {
display: inline;
}
}