Resumindo
- Um gradiente no canvas HTML é um objeto CanvasGradient criado com createLinearGradient, createRadialGradient ou createConicGradient, que recebe paradas de cor com addColorStop e é atribuído a fillStyle ou strokeStyle.
- Gradientes no canvas usam coordenadas no espaço do canvas, não ângulos nem porcentagens, então um gradiente linear precisa de um ponto inicial e um ponto final.
- Os offsets das paradas de cor vão de 0 a 1, e qualquer string de cor CSS é aceita, incluindo hex, rgb(), hsl() e oklch() nos navegadores atuais.
- O createConicGradient começa a varredura a partir de uma linha apontando para a direita e mede o ângulo em radianos, ao contrário do conic-gradient do CSS, que começa no topo e usa graus.
- Em telas de alta densidade, dimensione o buffer do canvas pelo devicePixelRatio, ou gradientes e textos ficam borrados.
Nesta página
Um gradiente no canvas HTML leva três passos: crie um objeto de gradiente com ctx.createLinearGradient(), createRadialGradient() ou createConicGradient(), adicione cores com addColorStop(offset, colour) e depois atribua a ctx.fillStyle e desenhe. Ao contrário do CSS, um gradiente no canvas é definido por pontos em pixels, então você diz exatamente onde a cor começa e termina. Tudo o que você pinta com esse preenchimento pega a parte do gradiente que está por baixo.
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)Os três métodos de gradiente
createLinearGradientArgumentos
x0, y0, x1, y1Equivalente em CSS
linear-gradient()createRadialGradientArgumentos
x0, y0, r0, x1, y1, r1Equivalente em CSS
radial-gradient()createConicGradientArgumentos
startAngle, x, yEquivalente em CSS
conic-gradient()addColorStopArgumentos
offset de 0 a 1, colourEquivalente em CSS
O gradiente fica preso ao canvas, não à forma. Se você cria um gradiente de 0 a 400 e depois preenche um quadradinho em x 300, o quadrado mostra só a ponta rosa. Isso surpreende quem vem do CSS, em que um gradiente sempre se estica até o tamanho do elemento. Crie o gradiente com as coordenadas da própria forma quando quiser que ele se encaixe.
createLinearGradient e ângulos CSS
O CSS deixa você escrever 135deg. O canvas quer dois pontos. Esta função converte um ângulo CSS nos mesmos pontos inicial e final que o CSS usa, para que um design escrito como gradiente linear em CSS apareça idêntico no 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
Um gradiente radial no canvas é definido por dois círculos: um círculo inicial e um círculo final. A parada de cor 0 fica no primeiro círculo e a parada 1, no segundo. Na maioria das vezes você quer que o primeiro círculo seja um ponto, então o raio dele é 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)Afaste o centro do primeiro círculo do segundo e a luz se inclina, como um holofote batendo em uma parede de lado. O CSS não tem um equivalente direto desse deslocamento. Para o lado do CSS, veja gradientes radiais em CSS.
createConicGradient
createConicGradient(startAngle, x, y) varre a cor em volta de um ponto central. Dois detalhes diferem do CSS: o ângulo é em radianos, e 0 aponta para a direita (três horas), não para cima. Para igualar um conic-gradient(from 0deg, ...) do CSS, comece em -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 com gradiente, contornos e animação
fillStyle e strokeStyle aceitam gradientes, então textos e contornos funcionam do mesmo jeito. Posicione o gradiente sobre a caixa do próprio texto, medida com measureText(), para que toda a faixa de cores apareça dentro das 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)Salvar o canvas como imagem
Um motivo comum para desenhar gradientes no canvas é gerar uma imagem: um card de compartilhamento, um certificado, uma capa. Chame canvas.toBlob() com image/png para gradientes e texto, porque o PNG mantém as transições suaves intactas, e use JPEG só quando a imagem for quase toda fotografia. PNG ou JPG explica a troca. Desenhe no tamanho real de saída, como 1200×630 para a prévia de um link, em vez de ampliar um canvas pequeno.
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 comuns com gradientes no canvas
Sintoma
- O gradiente fica borrado no celular
- Só aparece uma cor em uma forma
- Faixas visíveis em um gradiente escuro
IndexSizeErrorvindo do addColorStop- O gradiente cônico começa no lugar errado
Solução
- Multiplique a largura e a altura do canvas por
devicePixelRatioe volte comctx.scale() - Crie o gradiente com as coordenadas da forma, não do canvas
- Adicione um ruído leve por cima; veja banding em gradientes
- Mantenha os offsets entre 0 e 1
- Comece em
-Math.PI / 2para igualar o CSS
Quando você precisa de gradientes que se movem com iluminação real em vez de transições chapadas, o canvas chega ao limite e o WebGL assume, assunto de gradientes com shader. E quando o canvas é só um meio para chegar a uma imagem, como um card social ou um cartaz, o Gradiently renderiza um Mark em qualquer tamanho de 200 a 8.000 px com as palavras já diagramadas, então não há código de desenho para manter.
Perguntas frequentes
Como faço um gradiente em um canvas HTML?
Chame ctx.createLinearGradient(x0, y0, x1, y1), adicione cores com addColorStop(offset, colour), defina ctx.fillStyle como o gradiente e desenhe uma forma, como fillRect.
Qual a diferença entre createLinearGradient e o linear-gradient do CSS?
O canvas usa um ponto inicial e um ponto final em pixels, enquanto o CSS usa um ângulo e estica o gradiente até o elemento. Uma pequena função converte um ângulo CSS em pontos no canvas.
Posso usar cores oklch ou hsl no addColorStop?
Sim. O addColorStop aceita qualquer string de cor CSS que o navegador entenda, incluindo hex, rgb(), hsl() e, nos navegadores atuais, oklch().
Por que o meu gradiente no canvas mostra só uma cor?
O gradiente é posicionado em coordenadas do canvas, então uma forma desenhada fora dos pontos inicial e final pega só a cor da ponta mais próxima. Crie o gradiente usando a posição e o tamanho da forma.
Como animo um gradiente no canvas?
Crie um gradiente novo a cada quadro da animação, com paradas ou coordenadas atualizadas, e redesenhe. As paradas de um gradiente não podem ser movidas nem removidas depois de adicionadas.
Escrito pelo Gradiently
A equipe por trás do Gradiently, uma ferramenta de design criada em torno dos Marks: gradientes vivos que fazem tudo o que você cria ter a sua cara.
Ver nosso perfil