La versión corta
- Un degradado en canvas HTML es un objeto CanvasGradient creado con createLinearGradient, createRadialGradient o createConicGradient, al que se dan paradas de color con addColorStop y que se asigna a fillStyle o strokeStyle.
- Los degradados de canvas usan coordenadas en el espacio del canvas, no ángulos ni porcentajes, así que un degradado lineal necesita un punto inicial y un punto final.
- Los desplazamientos de las paradas de color van de 0 a 1, y se acepta cualquier cadena de color CSS, incluidos hex, rgb(), hsl() y oklch() en los navegadores actuales.
- createConicGradient empieza su barrido desde una línea que apunta a la derecha y mide el ángulo en radianes, a diferencia de conic-gradient en CSS, que empieza arriba y en grados.
- En pantallas de alta densidad, dimensiona el búfer del canvas según devicePixelRatio, o los degradados y el texto se verán borrosos.
En esta página
Un degradado en canvas HTML se hace en tres pasos: crea un objeto de degradado con ctx.createLinearGradient(), createRadialGradient() o createConicGradient(), añade colores con addColorStop(offset, colour) y asígnalo a ctx.fillStyle antes de dibujar. A diferencia de CSS, un degradado de canvas se define con puntos en píxeles, así que le dices exactamente dónde empieza y dónde acaba el color. Todo lo que pintes con ese relleno toma la parte del degradado que tiene debajo.
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
const g = ctx.createLinearGradient(0, 0, canvas.width, canvas.height)
g.addColorStop(0, '#1e1b4b')
g.addColorStop(0.55, '#7c3aed')
g.addColorStop(1, '#f472b6')
ctx.fillStyle = g
ctx.fillRect(0, 0, canvas.width, canvas.height)Los tres métodos de degradado
createLinearGradientArgumentos
x0, y0, x1, y1Equivalente en CSS
linear-gradient()createRadialGradientArgumentos
x0, y0, r0, x1, y1, r1Equivalente en CSS
radial-gradient()createConicGradientArgumentos
startAngle, x, yEquivalente en CSS
conic-gradient()addColorStopArgumentos
offset de 0 a 1, colourEquivalente en CSS
El degradado está fijado al canvas, no a la forma. Si creas un degradado de 0 a 400 y luego rellenas un cuadrado pequeño en x 300, el cuadrado solo muestra el extremo rosa. Eso sorprende a quien viene de CSS, donde un degradado siempre se estira al elemento. Crea el degradado con las coordenadas de la propia forma cuando quieras que encaje.
createLinearGradient y los ángulos de CSS
CSS te deja escribir 135deg. Canvas quiere dos puntos. Esta función convierte un ángulo CSS en los mismos puntos de inicio y fin que usa CSS, así que un diseño escrito como degradado lineal en CSS se dibuja idéntico en canvas.
// Match CSS linear-gradient(angle) on a w by h rectangle
function cssAngleGradient(ctx, angleDeg, x, y, w, h) {
const a = (angleDeg * Math.PI) / 180
const len = Math.abs(w * Math.sin(a)) + Math.abs(h * Math.cos(a))
const cx = x + w / 2
const cy = y + h / 2
const dx = (Math.sin(a) * len) / 2
const dy = (-Math.cos(a) * len) / 2
return ctx.createLinearGradient(cx - dx, cy - dy, cx + dx, cy + dy)
}
const g = cssAngleGradient(ctx, 135, 0, 0, 1200, 630)
g.addColorStop(0, '#0f172a')
g.addColorStop(1, '#0d9488')
ctx.fillStyle = g
ctx.fillRect(0, 0, 1200, 630)linear-gradient(135deg, #0f172a 0%, #0d9488 100%)createRadialGradient
Un degradado radial en canvas se define con dos círculos: uno inicial y uno final. La parada de color 0 está en el primer círculo y la parada 1 en el segundo. Casi siempre querrás que el primer círculo sea un punto, así que su radio es 0.
const w = canvas.width
const h = canvas.height
// A soft light in the top right corner of a dark ground
ctx.fillStyle = '#0c0a1d'
ctx.fillRect(0, 0, w, h)
const glow = ctx.createRadialGradient(w * 0.75, h * 0.2, 0, w * 0.75, h * 0.2, w * 0.6)
glow.addColorStop(0, 'rgb(124 58 237 / 0.9)')
glow.addColorStop(0.5, 'rgb(46 16 101 / 0.5)')
glow.addColorStop(1, 'rgb(12 10 29 / 0)')
ctx.fillStyle = glow
ctx.fillRect(0, 0, w, h)Aleja el centro del primer círculo del segundo y la luz se inclina, como un foco que da en una pared en ángulo. CSS no tiene un equivalente directo de ese desplazamiento. Para la parte de CSS, mira degradados radiales en CSS.
createConicGradient
createConicGradient(startAngle, x, y) hace girar el color alrededor de un punto central. Hay dos diferencias con CSS: el ángulo va en radianes, y 0 apunta a la derecha (las tres en punto), no hacia arriba. Para igualar un conic-gradient(from 0deg, ...) de CSS, empieza en -Math.PI / 2.
const cx = canvas.width / 2
const cy = canvas.height / 2
const ring = ctx.createConicGradient(-Math.PI / 2, cx, cy)
ring.addColorStop(0, '#22d3ee')
ring.addColorStop(0.33, '#7c3aed')
ring.addColorStop(0.66, '#f472b6')
ring.addColorStop(1, '#22d3ee')
ctx.fillStyle = ring
ctx.beginPath()
ctx.arc(cx, cy, 160, 0, Math.PI * 2)
ctx.fill()Texto degradado, trazos y animación
fillStyle y strokeStyle aceptan los dos un degradado, así que el texto y los contornos funcionan igual. Coloca el degradado sobre la caja del propio texto, medida con measureText(), para que toda la gama de colores aparezca dentro de las letras.
ctx.font = '700 96px Inter, system-ui, sans-serif'
const text = 'Open late'
const width = ctx.measureText(text).width
const tg = ctx.createLinearGradient(80, 0, 80 + width, 0)
tg.addColorStop(0, '#fde68a')
tg.addColorStop(1, '#fb7185')
ctx.fillStyle = tg
ctx.fillText(text, 80, 200)
// Animation: rebuild the gradient each frame, it is cheap
function frame(t) {
const shift = (Math.sin(t / 2000) + 1) / 2
const g = ctx.createLinearGradient(0, 0, canvas.width, 0)
g.addColorStop(0, '#1e1b4b')
g.addColorStop(0.2 + shift * 0.6, '#7c3aed')
g.addColorStop(1, '#0f172a')
ctx.fillStyle = g
ctx.fillRect(0, 0, canvas.width, canvas.height)
requestAnimationFrame(frame)
}
requestAnimationFrame(frame)Guardar el canvas como imagen
Un motivo habitual para dibujar degradados en canvas es generar una imagen: una tarjeta para compartir, un certificado, una portada. Llama a canvas.toBlob() con image/png para degradados y texto, porque PNG conserva intactas las mezclas suaves, y usa JPEG solo cuando la imagen sea sobre todo fotografía. PNG o JPG explica el equilibrio. Dibuja al tamaño real de salida, como 1200×630 para una vista previa de enlace, en lugar de ampliar un canvas pequeño.
canvas.toBlob((blob) => {
const a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = 'card.png'
a.click()
setTimeout(() => URL.revokeObjectURL(a.href), 1000)
}, 'image/png')Problemas habituales con los degradados de canvas
Síntoma
- El degradado se ve borroso en el móvil
- Solo aparece un color en una forma
- Bandas visibles en un degradado oscuro
IndexSizeErroren addColorStop- El degradado cónico empieza en el sitio equivocado
Solución
- Multiplica el ancho y el alto del canvas por
devicePixelRatioy compensa conctx.scale() - Crea el degradado con las coordenadas de la forma, no las del canvas
- Añade un ruido suave por encima, mira bandas en degradados
- Mantén los desplazamientos entre 0 y 1
- Empieza en
-Math.PI / 2para igualar CSS
Cuando necesitas degradados que se muevan con iluminación real en lugar de mezclas planas, el canvas llega a su límite y toma el relevo WebGL, como se explica en degradados con shaders. Y cuando el canvas es solo un medio para obtener una imagen, como una tarjeta para redes o un cartel, Gradiently renderiza un Mark a cualquier tamaño entre 200 y 8.000 px con las palabras ya maquetadas, así que no hay código de dibujo que mantener.
Preguntas frecuentes
¿Cómo hago un degradado en un canvas HTML?
Llama a ctx.createLinearGradient(x0, y0, x1, y1), añade colores con addColorStop(offset, colour), asigna el degradado a ctx.fillStyle y dibuja una forma, por ejemplo con fillRect.
¿Qué diferencia hay entre createLinearGradient y linear-gradient de CSS?
Canvas usa un punto inicial y un punto final en píxeles, mientras que CSS usa un ángulo y estira el degradado al elemento. Una pequeña función puede convertir un ángulo CSS en puntos de canvas.
¿Puedo usar colores oklch o hsl en addColorStop?
Sí. addColorStop acepta cualquier cadena de color CSS que entienda el navegador, incluidos hex, rgb(), hsl() y, en los navegadores actuales, oklch().
¿Por qué mi degradado de canvas solo muestra un color?
El degradado se sitúa en coordenadas del canvas, así que una forma dibujada fuera de sus puntos inicial y final solo toma el color del extremo más cercano. Crea el degradado con la posición y el tamaño de la forma.
¿Cómo animo un degradado de canvas?
Crea un degradado nuevo en cada fotograma de la animación con paradas o coordenadas actualizadas, y vuelve a dibujar. Las paradas de un degradado no se pueden mover ni quitar una vez añadidas.
Escrito por Gradiently
El equipo detrás de Gradiently, una herramienta de diseño creada en torno a los Marks: degradados vivos que hacen que todo lo que diseñas parezca tuyo.
Ver nuestro perfil