mirror of
https://codeberg.org/icewind/ptouch-api.git
synced 2026-06-03 10:54:07 +02:00
image support
This commit is contained in:
parent
88e6fa3244
commit
25f9e9b0a1
3 changed files with 103 additions and 29 deletions
|
|
@ -14,7 +14,8 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<td>
|
<td>
|
||||||
<input type="button" value="Add Text" id="add"/>
|
<input type="button" value="Add Text" id="add-text"/>
|
||||||
|
<input type="button" value="Add Image" id="add-image"/>
|
||||||
</td>
|
</td>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
||||||
123
web/label.js
123
web/label.js
|
|
@ -3,7 +3,8 @@ const elementsTable = document.getElementById('elements');
|
||||||
const preview = document.getElementById('preview');
|
const preview = document.getElementById('preview');
|
||||||
const renderCtx = preview.getContext("2d");
|
const renderCtx = preview.getContext("2d");
|
||||||
const elementsTableBody = elementsTable.getElementsByTagName('tbody')[0];
|
const elementsTableBody = elementsTable.getElementsByTagName('tbody')[0];
|
||||||
const addButton = document.getElementById('add');
|
const addTextButton = document.getElementById('add-text');
|
||||||
|
const addImageButton = document.getElementById('add-image');
|
||||||
/** @type HTMLInputElement printButton */
|
/** @type HTMLInputElement printButton */
|
||||||
const printButton = document.getElementById('print');
|
const printButton = document.getElementById('print');
|
||||||
const widthInput = document.getElementById('canvas-width');
|
const widthInput = document.getElementById('canvas-width');
|
||||||
|
|
@ -14,6 +15,8 @@ let defaultFontSize = 24;
|
||||||
let backgroundColor = "white";
|
let backgroundColor = "white";
|
||||||
let textColor = "white";
|
let textColor = "white";
|
||||||
|
|
||||||
|
let images = new Map();
|
||||||
|
|
||||||
const nextElementId = () => {
|
const nextElementId = () => {
|
||||||
let rows = elementsTableBody.getElementsByTagName('tr');
|
let rows = elementsTableBody.getElementsByTagName('tr');
|
||||||
if (rows.length === 0) {
|
if (rows.length === 0) {
|
||||||
|
|
@ -23,20 +26,7 @@ const nextElementId = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addElement = () => {
|
const addElementControls = (row) => {
|
||||||
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');
|
let sizeCol = document.createElement('td');
|
||||||
sizeCol.classList.add('size');
|
sizeCol.classList.add('size');
|
||||||
|
|
@ -44,7 +34,7 @@ const addElement = () => {
|
||||||
sizeInput.addEventListener('input', render);
|
sizeInput.addEventListener('input', render);
|
||||||
sizeInput.type = "number";
|
sizeInput.type = "number";
|
||||||
sizeInput.value = defaultFontSize.toString();
|
sizeInput.value = defaultFontSize.toString();
|
||||||
sizeCol.appendChild(document.createTextNode("Front size"))
|
sizeCol.appendChild(document.createTextNode("Size"))
|
||||||
sizeCol.appendChild(sizeInput);
|
sizeCol.appendChild(sizeInput);
|
||||||
row.appendChild(sizeCol);
|
row.appendChild(sizeCol);
|
||||||
}
|
}
|
||||||
|
|
@ -55,12 +45,12 @@ const addElement = () => {
|
||||||
let posInputX = document.createElement('input');
|
let posInputX = document.createElement('input');
|
||||||
posInputX.addEventListener('input', render);
|
posInputX.addEventListener('input', render);
|
||||||
posInputX.type = "number";
|
posInputX.type = "number";
|
||||||
posInputX.value = "2";
|
posInputX.value = "0";
|
||||||
posInputX.classList.add('pos_x');
|
posInputX.classList.add('pos_x');
|
||||||
let posInputY = document.createElement('input');
|
let posInputY = document.createElement('input');
|
||||||
posInputY.addEventListener('input', render);
|
posInputY.addEventListener('input', render);
|
||||||
posInputY.type = "number";
|
posInputY.type = "number";
|
||||||
posInputY.value = "2";
|
posInputY.value = "0";
|
||||||
posInputY.classList.add('pos_y');
|
posInputY.classList.add('pos_y');
|
||||||
posCol.appendChild(document.createTextNode("Position"))
|
posCol.appendChild(document.createTextNode("Position"))
|
||||||
posCol.appendChild(posInputX);
|
posCol.appendChild(posInputX);
|
||||||
|
|
@ -78,15 +68,67 @@ const addElement = () => {
|
||||||
removeCol.appendChild(removeInput);
|
removeCol.appendChild(removeInput);
|
||||||
row.appendChild(removeCol);
|
row.appendChild(removeCol);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const addTextElement = () => {
|
||||||
|
let id = nextElementId();
|
||||||
|
let row = document.createElement('tr');
|
||||||
|
row.dataset.elementId = id;
|
||||||
|
row.dataset.type = 'text';
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
addElementControls(row);
|
||||||
elementsTableBody.appendChild(row);
|
elementsTableBody.appendChild(row);
|
||||||
|
|
||||||
textInput.focus();
|
textInput.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadImage = (event) => {
|
||||||
|
/** @type HTMLInputElement input */
|
||||||
|
const input = event.target;
|
||||||
|
const row = event.target.parentElement.parentElement;
|
||||||
|
let file = input.files[0];
|
||||||
|
if (file.type.startsWith('image')) {
|
||||||
|
let image = row.getElementsByTagName('img')[0];
|
||||||
|
image.addEventListener('load', render);
|
||||||
|
image.src = URL.createObjectURL(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addImageElement = () => {
|
||||||
|
let id = nextElementId();
|
||||||
|
let row = document.createElement('tr');
|
||||||
|
row.dataset.elementId = id;
|
||||||
|
row.dataset.type = 'image';
|
||||||
|
|
||||||
|
|
||||||
|
let imageCol = document.createElement('td');
|
||||||
|
imageCol.classList.add('image');
|
||||||
|
let imageInput = document.createElement('input');
|
||||||
|
imageInput.type = 'file';
|
||||||
|
imageInput.addEventListener('change', loadImage);
|
||||||
|
let imageThumb = document.createElement('img');
|
||||||
|
imageCol.appendChild(imageInput);
|
||||||
|
imageCol.appendChild(imageThumb);
|
||||||
|
row.appendChild(imageCol);
|
||||||
|
|
||||||
|
addElementControls(row);
|
||||||
|
elementsTableBody.appendChild(row);
|
||||||
|
};
|
||||||
|
|
||||||
const removeElement = (event) => {
|
const removeElement = (event) => {
|
||||||
let row = event.target.parentElement.parentElement;
|
let row = event.target.parentElement.parentElement;
|
||||||
|
let id = row.dataset.elementId;
|
||||||
row.remove();
|
row.remove();
|
||||||
|
images.delete(id);
|
||||||
render();
|
render();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -94,12 +136,23 @@ 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) {
|
||||||
elements.push({
|
if (row.dataset.type === 'text') {
|
||||||
text: row.querySelector('.text input').value,
|
elements.push({
|
||||||
size: parseInt(row.querySelector('.size input').value, 10),
|
type: 'text',
|
||||||
x: parseInt(row.querySelector('.pos_x').value, 10),
|
text: row.querySelector('.text input').value,
|
||||||
y: parseInt(row.querySelector('.pos_y').value, 10),
|
size: parseInt(row.querySelector('.size input').value, 10),
|
||||||
});
|
x: parseInt(row.querySelector('.pos_x').value, 10),
|
||||||
|
y: parseInt(row.querySelector('.pos_y').value, 10),
|
||||||
|
});
|
||||||
|
} else if (row.dataset.type === 'image') {
|
||||||
|
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),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
@ -108,13 +161,26 @@ const render = () => {
|
||||||
let elements = getElements();
|
let elements = getElements();
|
||||||
let width = preview.width;
|
let width = preview.width;
|
||||||
let height = preview.height;
|
let height = preview.height;
|
||||||
|
renderCtx.filter = '';
|
||||||
renderCtx.fillStyle = backgroundColor;
|
renderCtx.fillStyle = backgroundColor;
|
||||||
renderCtx.fillRect(0, 0, width, height);
|
renderCtx.fillRect(0, 0, width, height);
|
||||||
|
|
||||||
renderCtx.fillStyle = textColor;
|
renderCtx.fillStyle = textColor;
|
||||||
for (let element of elements) {
|
for (let element of elements) {
|
||||||
renderCtx.font = `${element.size}px serif`;
|
if (element.type === 'text') {
|
||||||
renderCtx.fillText(element.text, element.x, height - element.y);
|
renderCtx.filter = '';
|
||||||
|
renderCtx.font = `${element.size}px serif`;
|
||||||
|
let textSize = renderCtx.measureText(element.text);
|
||||||
|
let textHeight = textSize.fontBoundingBoxAscent - textSize.emHeightDescent;
|
||||||
|
renderCtx.fillText(element.text, element.x, 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;
|
||||||
|
renderCtx.drawImage(element.image, element.x, element.y, element.size * ratio, element.size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,7 +209,8 @@ const print = () => {
|
||||||
}, 'image/png');
|
}, 'image/png');
|
||||||
};
|
};
|
||||||
|
|
||||||
addButton.addEventListener('click', addElement);
|
addTextButton.addEventListener('click', addTextElement);
|
||||||
|
addImageButton.addEventListener('click', addImageElement);
|
||||||
printButton.addEventListener('click', print);
|
printButton.addEventListener('click', print);
|
||||||
widthInput.addEventListener('input', resize);
|
widthInput.addEventListener('input', resize);
|
||||||
|
|
||||||
|
|
@ -168,5 +235,5 @@ fetch(apiRoot + '/status')
|
||||||
textColor = status.text_color;
|
textColor = status.text_color;
|
||||||
tapeWidthMM = status.media_width;
|
tapeWidthMM = status.media_width;
|
||||||
render();
|
render();
|
||||||
addElement();
|
addTextElement();
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
:root {
|
:root {
|
||||||
--background-color: #1e1e1e;
|
--background-color: #1e1e1e;
|
||||||
--font-color: #fff;
|
--font-color: #fff;
|
||||||
|
color-scheme: dark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -19,4 +20,9 @@ body, input {
|
||||||
.pos input {
|
.pos input {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image img {
|
||||||
|
height: 32px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue