# Gradiente su canvas HTML: createLinearGradient, radiale e conico

[Canonical HTML page](https://gradiently.design/it/guide/canvas-gradient)

I gradienti del canvas usano coordinate dove il CSS usa angoli, e questa sola differenza causa gran parte della confusione. Ecco ogni metodo con codice funzionante e una funzione che trasforma un angolo CSS in punti del canvas.

## The short version

- 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.

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.

```js
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)
```

Il più piccolo gradiente funzionante su canvas: una diagonale dall’angolo in alto a sinistra a quello in basso a destra.

## I tre metodi per i gradienti

| Metodo | Argomenti | Equivalente CSS |
| --- | --- | --- |
| `createLinearGradient` | `x0, y0, x1, y1` | `linear-gradient()` |
| `createRadialGradient` | `x0, y0, r0, x1, y1, r1` | `radial-gradient()` |
| `createConicGradient` | `startAngle, x, y` | `conic-gradient()` |
| `addColorStop` | `offset` da 0 a 1, `colore` | Un punto colore con una percentuale |

Ogni metodo restituisce un CanvasGradient. Puoi tenerlo in una variabile e riusarlo per quante forme vuoi.

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](https://gradiently.design/it/guide/css-linear-gradient) si disegna in modo identico sul canvas.

```js
// 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)
```

In CSS, 0deg punta in alto e gli angoli girano in senso orario. La formula della lunghezza fa cadere gli angoli esattamente sul primo e sull’ultimo colore, come fa il CSS.

Lo stesso gradiente in CSS: `linear-gradient(135deg, #0f172a 0%, #0d9488 100%)`

Ciò che la funzione qui sopra disegna su un canvas 1200×630, la dimensione di un’[immagine Open Graph](https://gradiently.design/it/guide/open-graph-tags). Se gli angoli sembrano sbagliati, l’[angolo del gradiente](https://gradiently.design/it/guide/gradient-angle) spiega come li misura il CSS.

## 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.

```js
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)
```

Sfumare l’ultimo punto fino alla trasparenza permette di sovrapporre più luci su un unico fondo, ed è così che si costruiscono gli sfondi a strati.

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](https://gradiently.design/it/guide/css-radial-gradient).

## 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`.

```js
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()
```

Ripetere il primo colore all’offset 1 nasconde la giunzione. createConicGradient funziona negli attuali Chrome, Edge, Safari e Firefox.

- createLinearGradient: `linear-gradient(135deg, #1e1b4b 0%, #7c3aed 55%, #f472b6 100%)`
- createRadialGradient: `radial-gradient(circle at 75% 20%, #7c3aed 0%, #2e1065 30%, #0c0a1d 60%)`
- createConicGradient: `conic-gradient(from 0deg, #22d3ee, #7c3aed, #f472b6, #22d3ee)`

I tre esempi di questo articolo, mostrati come i loro gemelli CSS. I [gradienti conici CSS](https://gradiently.design/it/guide/css-conic-gradient) trattano la versione conica più a fondo.

## 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.

```js
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)
```

Un punto colore, una volta aggiunto, non si può spostare né rimuovere, quindi per animare crea un nuovo gradiente a ogni fotogramma. Metti in pausa il ciclo per chi preferisce meno movimento.

## 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](https://gradiently.design/it/guide/png-vs-jpeg) spiega il compromesso. Disegna alla dimensione reale di output, come 1200×630 per l’anteprima di un link, invece di ingrandire un canvas piccolo.

```js
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')
```

Scarica il canvas finito come PNG. Su un server, lo stesso codice di disegno funziona con una libreria canvas per Node.

## 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
- `IndexSizeError` da addColorStop
- Il gradiente conico parte dal punto sbagliato

### Soluzione

- Moltiplica larghezza e altezza del canvas per `devicePixelRatio`, poi `ctx.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](https://gradiently.design/it/guide/gradient-banding)
- Tieni gli offset tra 0 e 1
- Parti da `-Math.PI / 2` per corrispondere al CSS

> **Colore più ampio sugli schermi adatti** Chrome e Safari accettano `canvas.getContext('2d', { colorSpace: 'display-p3' })`, che permette ai gradienti vivaci di usare la gamma P3 più ampia. I browser che non lo supportano ripiegano su sRGB.

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](https://gradiently.design/it/guide/shader-gradients). 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.

## FAQ

### 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.
