Dibujando en la Web
El lienzo que reemplazó a Flash: gráficos 2D, animaciones, video y mucho más.
Elemento <canvas> crea un área de dibujo. Atributos: width y height.
<canvas id="canvas" width="500" height="300"></canvas>
Contexto Se obtiene con getContext('2d') o 'webgl' (3D).
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d');
WebGL se estudia en el próximo capítulo. Todos los navegadores modernos soportan 2d.
fillRect(x, y, w, h) — rellenostrokeRect(x, y, w, h) — contornoclearRect(x, y, w, h) — borradorctx.strokeRect(100,100,120,120); ctx.fillRect(110,110,100,100); ctx.clearRect(120,120,80,80);
fillStyle — rellenostrokeStyle — líneaglobalAlpha — transparencia (0.0–1.0)ctx.fillStyle = '#000099'; ctx.strokeStyle = 'rgba(255,0,0,0.7)';
Los colores usan sintaxis CSS: hexadecimales, rgb(), rgba().
createLinearGradient(), createRadialGradient() y addColorStop().
Un trazado es un "mapa" que el lápiz sigue. Se inicia con beginPath() y se dibuja con stroke(), fill() o clip().
moveTo(x, y)lineTo(x, y)rect(x, y, w, h)arc(x, y, r, a1, a2, dir)quadraticCurveTo(cpx, cpy, x, y)bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)ctx.beginPath(); ctx.moveTo(100,100); ctx.lineTo(200,200); ctx.lineTo(100,200); ctx.closePath(); // opcional ctx.stroke(); // o .fill()
fill() cierra automáticamente el trazado. clip() crea una máscara de recorte.
lineWidth — grosorlineCap — extremos: butt, round, squarelineJoin — uniones: round, bevel, mitermiterLimit — límite del picofont — igual que CSStextAlign / textBaselinefillText(text, x, y)strokeText(text, x, y)measureText(text) — devuelve widthshadowColor, shadowOffsetX, shadowOffsetY, shadowBlurctx.shadowColor = 'rgba(0,0,0,0.5)'; ctx.shadowOffsetX = 4; ctx.shadowOffsetY = 4; ctx.shadowBlur = 5; ctx.font = 'bold 50px verdana'; ctx.fillText('Mi Mensaje', 100, 100);
translate(x, y) — mover origenrotate(ángulo) — radianesscale(x, y) — escalar (negativos = espejo)transform(m1,m2,m3,m4,dx,dy) — matrizsetTransform(...) — reinicia y aplicasave() — guarda el estado actualrestore() — recupera el último guardadoAcumulativas: cada transformación se suma a la anterior.
ctx.save(); ctx.translate(50,70); ctx.rotate(Math.PI/4); ctx.fillText('Rotado', 0, 0); ctx.restore();
globalCompositeOperation 12 modos de combinación (source-over, xor, destination-in, etc.)
drawImage(imagen, x, y) — 3 versiones: simple, con escalado, y con recorte.
<img>, <video> o <canvas>load para asegurar descargaconst img = document.createElement('img'); img.src = 'foto.jpg'; img.onload = () => ctx.drawImage(img, 20, 20);
createPattern(imagen, tipo) — repeat, repeat-x, repeat-y, no-repeat
getImageData(x, y, w, h) → objeto con data (RGBA)putImageData(imagenData, x, y)Acceso por píxeles: data[(w*4*y) + (x*4) + n]
⚠️ Origen cruzado: usar crossOrigin="anonymous" y cabeceras CORS.
No hay un método mágico: se borra el lienzo y se redibuja en cada fotograma.
requestAnimationFrame(fn) — sincronizado con el refresco del navegador.
function bucle() { ctx.clearRect(0,0,500,300); dibujar(); requestAnimationFrame(bucle); }
mousemoveMath.atan2() para el ánguloMath.sin() y Math.cos() para posición del irisTambién se puede usar setInterval() pero es menos fluido.
drawImage(video, x, y) dibuja el fotograma actual del <video>.
const video = document.getElementById('medio'); setInterval(() => { ctx.drawImage(video, 0, 0); }, 33); // ~30 fps
ctx.translate(ancho, 0); ctx.scale(-1, 1);
navigator.mediaDevices.getUserMedia({video: true})<video> y capturar fotogramas en <canvas>toDataURL() o toBlob()© Video: Big Buck Bunny (Blender Foundation)
canvas.toDataURL('image/png') → cadena data:urlcanvas.toBlob(callback, 'image/jpeg') → objeto BlobÚtil para guardar, compartir o subir al servidor.
¡El lienzo es el límite! 🚀
developer.mozilla.org