JSFiddle - React, Tailwind, and code Playground
HTML
<html>
<body>
<div id="main"></div>
</body>
</html>
TypeScript
/**
* Una vez completada la carga de la página iniciamos el proceso de firma
*/
document.addEventListener('DOMContentLoaded', async () => {
const container = document.querySelector('div#main') as HTMLElement;
if (container) {
// Prepara el contenedor
container.innerHTML = '';
container.style.height = '100vh';
container.style.display = 'flex';
container.style.alignItems = 'center';
container.style.justifyContent = 'center';
container.style.background = '#eee';
container.style.overflow = 'hidden';
container.style.touchAction = 'none';
// Crea el canvas
const canvas = document.createElement('canvas');
canvas.width = 400;
canvas.height = 300;
canvas.style.border = '2px solid black';
canvas.style.background = 'white';
container.appendChild(canvas);
const ctx = canvas.getContext('2d')!;
ctx.lineWidth = 2;
ctx.strokeStyle = 'blue';
ctx.lineCap = 'round';
let drawing = false;
let lastX = 0;
let lastY = 0;
const getPos = (e: PointerEvent) => {
const rect = canvas.getBoundingClientRect();
return {
x: e.clientX - rect.left,
y: e.clientY - rect.top,
};
};
canvas.addEventListener('pointerdown', e => {
e.preventDefault();
const pos = getPos(e);
lastX = pos.x;
lastY = pos.y;
drawing = true;
});
canvas.addEventListener('pointermove', e => {
if (!drawing) return;
e.preventDefault();
const pos = getPos(e);
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(pos.x, pos.y);
ctx.stroke();
lastX = pos.x;
lastY = pos.y;
});
canvas.addEventListener('pointerup', () => (drawing = false));
canvas.addEventListener('pointerleave', () => (drawing = false));
console.log('✅ Canvas listo. Si ves un rectángulo blanco con borde negro, dibuja con el dedo o ratón.');
} else {
console.warn('No se encontró el div#main');
}
});