In breve
- Un gradiente su canvas HTML è un oggetto CanvasGradient creato con createLinearGradient, createRadialGradient o createConicGradient, riempito di punti colore con addColorStop e assegnato a fillStyle o strokeStyle.
- I gradienti del canvas usano coordinate nello spazio del canvas, non angoli né percentuali, quindi un gradiente lineare richiede un punto iniziale e uno finale.
- Gli offset dei punti colore vanno da 0 a 1 e qualsiasi stringa di colore CSS è accettata, inclusi hex, rgb(), hsl() e oklch() nei browser attuali.
- createConicGradient parte da una linea che punta a destra e misura l’angolo in radianti, a differenza del conic-gradient CSS, che parte dall’alto e usa i gradi.
- Sugli schermi ad alta densità, dimensiona il buffer del canvas con devicePixelRatio, altrimenti gradienti e testo appaiono sfocati.
In questa pagina
Un gradiente su canvas HTML richiede tre passaggi: creare un oggetto gradiente con ctx.createLinearGradient(), createRadialGradient() o createConicGradient(), aggiungere i colori con addColorStop(offset, colore), poi assegnarlo a ctx.fillStyle e disegnare. A differenza del CSS, un gradiente del canvas è definito da punti in pixel, quindi indichi esattamente dove il colore inizia e finisce. Tutto ciò che dipingi con quel riempimento prende la parte di gradiente che gli sta sotto.
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)I tre metodi per i gradienti
createLinearGradientArgomenti
x0, y0, x1, y1Equivalente CSS
linear-gradient()createRadialGradientArgomenti
x0, y0, r0, x1, y1, r1Equivalente CSS
radial-gradient()createConicGradientArgomenti
startAngle, x, yEquivalente CSS
conic-gradient()addColorStopArgomenti
offset da 0 a 1, coloreEquivalente CSS
Il gradiente è fissato al canvas, non alla forma. Se crei un gradiente da 0 a 400 e poi riempi un piccolo quadrato a x 300, il quadrato mostra solo l’estremo rosa. Sorprende chi arriva dal CSS, dove un gradiente si estende sempre all’elemento. Crea il gradiente con le coordinate della forma quando vuoi che le si adatti.
createLinearGradient e angoli CSS
Il CSS ti lascia scrivere 135deg. Il canvas vuole due punti. Questa funzione converte un angolo CSS negli stessi punti iniziale e finale che usa il CSS, così un design scritto come gradiente lineare CSS si disegna in modo identico sul 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 gradiente radiale sul canvas è definito da due cerchi: uno iniziale e uno finale. Il punto colore 0 sta sul primo cerchio e il punto 1 sul secondo. Per lo più vuoi che il primo cerchio sia un punto, quindi con raggio 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)Sposta il centro del primo cerchio lontano dal secondo e la luce si inclina, come un faro che colpisce un muro di sbieco. Il CSS non ha un equivalente diretto di quello scarto. Per il lato CSS, vedi i gradienti radiali CSS.
createConicGradient
createConicGradient(startAngle, x, y) fa girare il colore attorno a un centro. Due dettagli differiscono dal CSS: l’angolo è in radianti e 0 punta a destra (le tre), non verso l’alto. Per ottenere un conic-gradient(from 0deg, ...) CSS, parti da -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()Testo, contorni e animazione con i gradienti
fillStyle e strokeStyle accettano entrambi un gradiente, quindi testo e contorni funzionano allo stesso modo. Imposta il gradiente sul riquadro del testo, misurato con measureText(), così l’intera gamma di colori appare dentro le lettere.
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)Salvare il canvas come immagine
Un motivo comune per disegnare gradienti sul canvas è generare un’immagine: una card da condividere, un certificato, una copertina. Chiama canvas.toBlob() con image/png per gradienti e testo, perché il PNG mantiene intatte le sfumature morbide, e usa il JPEG solo quando l’immagine è per lo più una fotografia. PNG o JPG spiega il compromesso. Disegna alla dimensione reale di output, come 1200×630 per l’anteprima di un link, invece di ingrandire un canvas piccolo.
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')Problemi comuni dei gradienti su canvas
Sintomo
- Il gradiente appare sfocato su un telefono
- In una forma si vede un solo colore
- Strisce visibili in un gradiente scuro
IndexSizeErrorda addColorStop- Il gradiente conico parte dal punto sbagliato
Soluzione
- Moltiplica larghezza e altezza del canvas per
devicePixelRatio, poictx.scale()per tornare indietro - Crea il gradiente con le coordinate della forma, non del canvas
- Aggiungi sopra un leggero rumore, vedi le bande nei gradienti
- Tieni gli offset tra 0 e 1
- Parti da
-Math.PI / 2per corrispondere al CSS
Quando servono gradienti che si muovono con una vera illuminazione invece di sfumature piatte, il canvas raggiunge i suoi limiti e subentra WebGL, trattato nei gradienti shader. E quando il canvas è solo un mezzo per ottenere un’immagine, come una card social o un poster, Gradiently disegna un Mark a qualsiasi dimensione da 200 a 8.000 px con le parole già impaginate, quindi non c’è codice di disegno da mantenere.
Le domande più frequenti
Come faccio un gradiente su un canvas HTML?
Chiama ctx.createLinearGradient(x0, y0, x1, y1), aggiungi i colori con addColorStop(offset, colore), imposta ctx.fillStyle sul gradiente e disegna una forma come fillRect.
Che differenza c’è tra createLinearGradient e il linear-gradient CSS?
Il canvas usa un punto iniziale e uno finale in pixel, mentre il CSS usa un angolo ed estende il gradiente all’elemento. Una piccola funzione può convertire un angolo CSS in punti del canvas.
Posso usare colori oklch o hsl in addColorStop?
Sì. addColorStop accetta qualsiasi stringa di colore CSS che il browser capisca, inclusi hex, rgb(), hsl() e, nei browser attuali, oklch().
Perché il mio gradiente su canvas mostra un solo colore?
Il gradiente è posizionato in coordinate del canvas, quindi una forma disegnata fuori dai suoi punti iniziale e finale prende solo il colore dell’estremo più vicino. Crea il gradiente usando posizione e dimensione della forma.
Come animo un gradiente su canvas?
Crea un nuovo gradiente a ogni fotogramma con punti o coordinate aggiornati e ridisegna. I punti di un gradiente non si possono spostare né rimuovere una volta aggiunti.
Scritto da Gradiently
Il team dietro Gradiently, uno strumento di design costruito attorno ai Mark: gradienti vivi che fanno sembrare tuo tutto ciò che progetti.
Vedi il nostro profilo