Gradienti Canvas
I gradienti HTML5 Canvas sono pattern di colori per riempire cerchi, rettangoli, linee, testo e altro. Scopri i gradienti lineari e radiali.
Un gradiente, in generale, è un pattern di colori che cambia gradualmente da un colore a un altro. I gradienti HTML5 Canvas ti permettono di riempire o tracciare forme — cerchi, rettangoli, linee, testo, percorsi arbitrari — con questo tipo di fusione multicolore invece di un singolo colore solido.
Questo capitolo tratta i tre tipi di gradiente che puoi creare in un contesto canvas 2D, come i loro parametri di coordinate controllano direzione e dimensione, come addColorStop() posiziona i colori lungo il gradiente, e diversi esempi eseguibili (verticale, diagonale, riempimenti di testo/percorso e un bagliore radiale). Se sei nuovo all'API canvas, inizia con l'introduzione a HTML5 Canvas, poi disegnare forme e percorsi, e rivedi come funziona il sistema di coordinate del canvas.
Come funzionano i gradienti canvas
Lavorare con un gradiente segue sempre gli stessi quattro passaggi:
- Crea un oggetto gradiente con uno dei metodi factory del contesto:
ctx.createLinearGradient(x0, y0, x1, y1)— un gradiente lineare (direzionale).ctx.createRadialGradient(x0, y0, r0, x1, y1, r1)— un gradiente radiale (circolare).ctx.createConicGradient(startAngle, x, y)— un gradiente conico (scorrimento angolare).
- Aggiungi due o più color stop con
gradient.addColorStop(offset, color). - Assegna il gradiente a
ctx.fillStyleoctx.strokeStyle. - Disegna una forma (
fillRect,fill,stroke,fillText, …). Il gradiente viene campionato ovunque tu dipinga.
Una cosa fondamentale da capire: le coordinate del gradiente sono nello spazio del canvas (assoluto), non relative alla forma che stai riempiendo. Un gradiente creato da (0, 0) a (300, 0) si estende sempre in quella regione del canvas. Se disegni un rettangolo al di fuori di quell'intervallo, il rettangolo assume il primo o l'ultimo colore del gradiente (quello più vicino), perché i colori prima dell'offset 0 e dopo l'offset 1 vengono bloccati.
addColorStop(): posizionare i colori
gradient.addColorStop(offset, color) aggiunge un color stop al gradiente.
offset— un numero compreso tra0.0(l'inizio del gradiente) e1.0(la fine). Valori al di fuori di questo intervallo generano un errore.color— qualsiasi stringa di colore CSS: un nome ("green"), esadecimale ("#14389c"),rgb()/rgba(), oppurehsl(). Usa il canale alfa (rgba(...)) per i stop trasparenti.
Hai bisogno di almeno due stop per una fusione visibile. L'offset di ciascun stop controlla dove avviene la transizione — più piccolo è il divario tra due offset, più netto è il cambiamento di colore tra di essi. Una spaziatura uniforme produce una fusione omogenea; raggruppare gli offset crea bande nette.
<!DOCTYPE html>
<html>
<head>
<title>Three color stops</title>
<style>
canvas { border: 1px solid #cccccc; }
</style>
</head>
<body>
<canvas id="stopsCanvas" width="300" height="120"></canvas>
<script>
const ctx = document.getElementById("stopsCanvas").getContext("2d");
const grd = ctx.createLinearGradient(0, 0, 300, 0);
grd.addColorStop(0, "red"); // start
grd.addColorStop(0.5, "yellow"); // exact middle
grd.addColorStop(1, "green"); // end
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 300, 120);
</script>
</body>
</html>Sposta il middle stop da 0.5 a 0.85 e la banda gialla si sposta molto verso destra, lasciando la maggior parte della barra come fusione dal rosso al giallo — questo è l'offset che controlla il posizionamento.
Gradiente Lineare
ctx.createLinearGradient(x0, y0, x1, y1) restituisce un gradiente i cui colori cambiano lungo una linea retta — il vettore gradiente che va dal punto iniziale (x0, y0) al punto finale (x1, y1):
x0, y0— il punto iniziale del gradiente. Il color stop all'offset0viene dipinto qui.x1, y1— il punto finale del gradiente. Il color stop all'offset1viene dipinto qui.
La direzione della linea tra questi due punti determina la direzione del gradiente, e la distanza tra di essi determina quanto si estende la fusione. Le linee tracciate perpendicolarmente al vettore hanno un singolo colore solido.
- Un gradiente orizzontale mantiene
yuguale:createLinearGradient(0, 0, 300, 0). - Un gradiente verticale mantiene
xuguale:createLinearGradient(0, 0, 0, 200). - Un gradiente diagonale cambia entrambi:
createLinearGradient(0, 0, 300, 200).
Ricorda il sistema di coordinate del canvas: (0, 0) è l'angolo in alto a sinistra, x aumenta verso destra e y aumenta verso il basso.
Esempio di gradiente lineare orizzontale usando fillStyle
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
canvas {
border: 1px solid #cccccc;
}
</style>
</head>
<body>
<canvas id="exampleCanvas" width="300" height="150">
Your browser doesn't support the HTML5 canvas tag.
</canvas>
<script>
var c = document.getElementById("exampleCanvas");
var ctx = c.getContext("2d");
var grd = ctx.createLinearGradient(0, 0, 300, 0);
grd.addColorStop(0, "green");
grd.addColorStop(1, "whitesmoke");
ctx.fillStyle = grd;
ctx.fillRect(20, 20, 260, 110);
</script>
</body>
</html>Poiché il vettore va da (0, 0) a (300, 0), la fusione è puramente orizzontale: il bordo sinistro è verde e il bordo destro è whitesmoke.
Esempio di gradiente lineare verticale
Mantieni x uguale in entrambi i punti (qui 0) e cambia solo y per fondere dall'alto verso il basso:
<!DOCTYPE html>
<html>
<head>
<title>Vertical gradient</title>
<style>
canvas { border: 1px solid #cccccc; }
</style>
</head>
<body>
<canvas id="verticalCanvas" width="300" height="200"></canvas>
<script>
const ctx = document.getElementById("verticalCanvas").getContext("2d");
// Same x (0), different y → top-to-bottom blend.
const grd = ctx.createLinearGradient(0, 0, 0, 200);
grd.addColorStop(0, "#1e3c72"); // top
grd.addColorStop(1, "#2a5298"); // bottom
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 300, 200);
</script>
</body>
</html>Esempio di gradiente lineare diagonale
Cambia sia x che y in modo che il vettore vada da angolo ad angolo:
<!DOCTYPE html>
<html>
<head>
<title>Diagonal gradient</title>
<style>
canvas { border: 1px solid #cccccc; }
</style>
</head>
<body>
<canvas id="diagonalCanvas" width="300" height="200"></canvas>
<script>
const ctx = document.getElementById("diagonalCanvas").getContext("2d");
// Vector from the top-left corner to the bottom-right corner.
const grd = ctx.createLinearGradient(0, 0, 300, 200);
grd.addColorStop(0, "#ff512f");
grd.addColorStop(0.5, "#f09819");
grd.addColorStop(1, "#ffd452");
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 300, 200);
</script>
</body>
</html>Esempio di gradiente lineare usando fillStyle con colori diversi:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
canvas {
border: 2px solid #202131;
}
</style>
</head>
<body>
<canvas id="exampleCanvas" width="500" height="200"></canvas>
<script>
var canvas = document.getElementById('exampleCanvas');
var context = canvas.getContext('2d');
context.rect(0, 0, 500, 200);
var linear = context.createLinearGradient(0, 0, 500, 200);
linear.addColorStop(0, '#297979');
linear.addColorStop(1, '#2ee035');
context.fillStyle = linear;
context.fill();
</script>
</body>
</html>Esempio di gradiente lineare usando fillStyle e strokeStyle:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
canvas {
border: 5px solid #cccccc;
}
</style>
<script>
function drawShape() {
var canvas = document.getElementById('canvasGradient');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var lgrad1 = ctx.createLinearGradient(0, 0, 0, 300);
lgrad1.addColorStop(0, 'blue');
lgrad1.addColorStop(0.4, 'lightpink');
lgrad1.addColorStop(0.5, 'purple');
lgrad1.addColorStop(1, 'lightsalmon');
var lgrad2 = ctx.createLinearGradient(0, 50, 0, 150);
lgrad2.addColorStop(0, '#7afff3');
lgrad2.addColorStop(0.5, '#191918');
lgrad2.addColorStop(1, '#7afff3');
ctx.fillStyle = lgrad1;
ctx.strokeStyle = lgrad2;
ctx.fillRect(15, 15, 120, 120);
ctx.strokeRect(100, 50, 100, 50);
} else {
alert('Your browser does not support');
}
}
</script>
</head>
<body onload="drawShape();">
<canvas id="canvasGradient" width="300" height="300"></canvas>
</body>
</html>Esempio di gradiente su testo e un percorso
Un gradiente non è limitato ai rettangoli — funziona con qualsiasi riempimento o tratto, inclusi testo e percorsi personalizzati. Impostalo come fillStyle prima di fillText() (vedi disegnare testo sul canvas), oppure prima di fill()/stroke() su un percorso che hai costruito (vedi disegnare sul canvas).
<!DOCTYPE html>
<html>
<head>
<title>Gradient text and path</title>
<style>
canvas { border: 1px solid #cccccc; }
</style>
</head>
<body>
<canvas id="textCanvas" width="400" height="160"></canvas>
<script>
const ctx = document.getElementById("textCanvas").getContext("2d");
// A gradient spanning the canvas width.
const grd = ctx.createLinearGradient(0, 0, 400, 0);
grd.addColorStop(0, "#8e2de2");
grd.addColorStop(1, "#4a00e0");
// Fill text with the gradient.
ctx.font = "bold 48px sans-serif";
ctx.fillStyle = grd;
ctx.fillText("Gradient", 30, 70);
// Stroke a triangular path with the same gradient.
ctx.beginPath();
ctx.moveTo(40, 100);
ctx.lineTo(360, 100);
ctx.lineTo(200, 145);
ctx.closePath();
ctx.lineWidth = 6;
ctx.strokeStyle = grd;
ctx.stroke();
</script>
</body>
</html>Gradiente Radiale
ctx.createRadialGradient(x0, y0, r0, x1, y1, r1) definisce un gradiente tra due cerchi. Il colore si fonde verso l'esterno dal cerchio iniziale al cerchio finale:
x0, y0, r0— il centro(x0, y0)e il raggior0del cerchio iniziale (interno). Il color stop all'offset0riempie questo cerchio.x1, y1, r1— il centro(x1, y1)e il raggior1del cerchio finale (esterno). Il color stop all'offset1viene raggiunto al bordo di questo cerchio.
Quando entrambi i cerchi condividono lo stesso centro, si ottiene un bagliore perfettamente concentrico. Quando il centro del cerchio interno è spostato rispetto a quello esterno, il punto luminoso si sposta su un lato — questo è esattamente come si simula una sorgente luminosa o un riflesso lucido (l'esempio seguente usa centri sfasati). Impostare r0 maggiore di 0 produce un nucleo solido del primo colore prima che inizi la fusione.
Esempio di gradiente radiale con centri sfasati
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
canvas {
border: 2px solid #cccccc;
}
</style>
</head>
<body>
<canvas id="exampleCanvas" width="300" height="150">
Your browser doesn't support the HTML5 canvas tag.
</canvas>
<script>
var c = document.getElementById("exampleCanvas");
var ctx = c.getContext("2d");
var grd = ctx.createRadialGradient(155, 80, 20, 130, 40, 190);
grd.addColorStop(0, "#14389c");
grd.addColorStop(1, "white");
ctx.fillStyle = grd;
ctx.fillRect(15, 15, 270, 120);
</script>
</body>
</html>Qui il cerchio interno è centrato in (155, 80) con raggio 20, mentre il cerchio esterno è centrato in (130, 40) con raggio 190. Poiché i centri differiscono, il nucleo blu scuro si trova verso il basso a destra e sfuma verso il bianco fuori centro, conferendo al riempimento un aspetto tridimensionale, illuminato da un lato.
Esempio di bagliore radiale
Un piccolo stop esterno completamente trasparente su una regione trasparente del canvas crea un bagliore morbido che puoi sovrapporre ad altri disegni. Nota l'uso di rgba() in modo che il bordo sfumi nel nulla invece che nel bianco:
<!DOCTYPE html>
<html>
<head>
<title>Radial glow</title>
<style>
canvas { border: 1px solid #cccccc; background: #11131f; }
</style>
</head>
<body>
<canvas id="glowCanvas" width="300" height="200"></canvas>
<script>
const ctx = document.getElementById("glowCanvas").getContext("2d");
// Concentric circles: solid core at (150,100), fading out to radius 110.
const grd = ctx.createRadialGradient(150, 100, 5, 150, 100, 110);
grd.addColorStop(0, "rgba(255, 214, 102, 1)"); // bright core
grd.addColorStop(0.4, "rgba(255, 154, 0, 0.6)"); // warm mid
grd.addColorStop(1, "rgba(255, 154, 0, 0)"); // transparent edge
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 300, 200);
</script>
</body>
</html>Gradiente Conico
ctx.createConicGradient(startAngle, x, y) crea un gradiente che scorre i colori attorno a un punto centrale, come una ruota dei colori o un grafico a torta, anziché lungo una linea o tra cerchi:
startAngle— l'angolo in radianti in cui l'offset0inizia, misurato in senso orario dall'asse x positivo.x, y— il punto centrale della rotazione.
I color stop sono posizionati attorno all'intera rotazione, quindi l'offset 0 e l'offset 1 si incontrano nuovamente in startAngle. Per evitare una giuntura visibile, assegna ai primi e agli ultimi stop lo stesso colore.
<!DOCTYPE html>
<html>
<head>
<title>Conic gradient</title>
<style>
canvas { border: 1px solid #cccccc; }
</style>
</head>
<body>
<canvas id="conicCanvas" width="200" height="200"></canvas>
<script>
const ctx = document.getElementById("conicCanvas").getContext("2d");
// Sweep starting at the top (-90° = -Math.PI/2), centered at (100,100).
const grd = ctx.createConicGradient(-Math.PI / 2, 100, 100);
grd.addColorStop(0, "red");
grd.addColorStop(0.25, "yellow");
grd.addColorStop(0.5, "lime");
grd.addColorStop(0.75, "blue");
grd.addColorStop(1, "red"); // matches stop 0 → seamless wheel
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 200, 200);
</script>
</body>
</html>createConicGradient() è supportato nelle versioni attuali di tutti i principali browser (Chrome, Edge, Firefox e Safari). Fornisci un colore solido di fallback per i browser molto vecchi se devi supportarli.