Kortversionen
- En gradient i HTML canvas är ett CanvasGradient-objekt som skapas med createLinearGradient, createRadialGradient eller createConicGradient, får färgstopp med addColorStop och tilldelas fillStyle eller strokeStyle.
- Gradienter i canvas använder koordinater i canvasrymden, inte vinklar eller procent, så en linjär gradient behöver en startpunkt och en slutpunkt.
- Färgstoppens förskjutningar går från 0 till 1, och vilken CSS-färgsträng som helst accepteras, inklusive hex, rgb(), hsl() och oklch() i aktuella webbläsare.
- createConicGradient startar sin svepning från en linje som pekar åt höger och mäter vinkeln i radianer, till skillnad från CSS conic-gradient, som startar högst upp och räknar i grader.
- På skärmar med hög täthet bör du storleksanpassa canvasbufferten med devicePixelRatio, annars ser gradienter och text mjuka ut.
På den här sidan
En gradient i HTML canvas tar tre steg: skapa ett gradientobjekt med ctx.createLinearGradient(), createRadialGradient() eller createConicGradient(), lägg till färger med addColorStop(offset, colour) och tilldela det sedan till ctx.fillStyle och rita. Till skillnad från CSS definieras en gradient i canvas av punkter i pixlar, så du talar om exakt var färgen börjar och slutar. Allt du målar med den fyllningen får den del av gradienten som ligger under.
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)De tre gradientmetoderna
createLinearGradientArgument
x0, y0, x1, y1CSS-motsvarighet
linear-gradient()createRadialGradientArgument
x0, y0, r0, x1, y1, r1CSS-motsvarighet
radial-gradient()createConicGradientArgument
startAngle, x, yCSS-motsvarighet
conic-gradient()addColorStopArgument
offset 0 till 1, colourCSS-motsvarighet
Gradienten är fäst vid canvasen, inte vid formen. Om du skapar en gradient från 0 till 400 och sedan fyller en liten kvadrat vid x 300 visar kvadraten bara den rosa änden. Det överraskar den som kommer från CSS, där en gradient alltid sträcker sig över elementet. Skapa gradienten med formens egna koordinater när du vill att den ska passa.
createLinearGradient och CSS-vinklar
I CSS kan du skriva 135deg. Canvas vill ha två punkter. Den här hjälpfunktionen omvandlar en CSS-vinkel till samma start- och slutpunkter som CSS använder, så en design skriven som en linjär gradient i CSS återges identiskt i 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
En radiell gradient i canvas definieras av två cirklar: en startcirkel och en slutcirkel. Färgstopp 0 ligger på den första cirkeln och stopp 1 på den andra. För det mesta vill du att den första cirkeln ska vara en punkt, så dess radie är 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)Flytta mitten på den första cirkeln bort från den andra så lutar ljuset, som en strålkastare som träffar en vägg i vinkel. CSS har ingen direkt motsvarighet till den förskjutningen. För CSS-sidan, se radiella gradienter i CSS.
createConicGradient
createConicGradient(startAngle, x, y) sveper färg runt en mittpunkt. Två detaljer skiljer sig från CSS: vinkeln anges i radianer, och 0 pekar åt höger (klockan tre), inte uppåt. För att matcha en CSS-gradient conic-gradient(from 0deg, ...) startar du vid -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()Gradienttext, konturer och animation
fillStyle och strokeStyle accepterar båda en gradient, så text och konturer fungerar på samma sätt. Sätt gradienten över textens egen ruta, mätt med measureText(), så att hela färgspannet syns inuti bokstäverna.
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)Att spara canvasen som bild
En vanlig anledning att rita gradienter i canvas är att skapa en bild: ett delningskort, ett certifikat, ett omslag. Anropa canvas.toBlob() med image/png för gradienter och text, eftersom PNG bevarar mjuka övergångar intakta, och använd JPEG bara när bilden mest är ett fotografi. PNG mot JPG förklarar avvägningen. Rita i den verkliga utdatastorleken, som 1200×630 för en länkförhandsvisning, i stället för att skala upp en liten canvas.
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')Vanliga problem med gradienter i canvas
Symptom
- Gradienten ser suddig ut på en telefon
- Bara en färg syns i en form
- Synliga ränder i en mörk gradient
IndexSizeErrorfrån addColorStop- Den koniska gradienten startar på fel ställe
Lösning
- Multiplicera canvasens bredd och höjd med
devicePixelRatiooch skala sedan tillbaka medctx.scale() - Skapa gradienten med formens koordinater, inte canvasens
- Lägg lite brus ovanpå, se gradientbandning
- Håll förskjutningarna mellan 0 och 1
- Starta vid
-Math.PI / 2för att matcha CSS
När du behöver gradienter som rör sig med verklig belysning snarare än platta övergångar når canvas sin gräns och WebGL tar över, vilket beskrivs i shadergradienter. Och när canvasen bara är ett medel för att få en bild, som ett socialt kort eller en affisch, renderar Gradiently en Mark i vilken storlek som helst från 200 till 8 000 px med orden utlagda åt dig, så det finns ingen ritkod att underhålla.
Vanliga frågor
Hur gör jag en gradient i en HTML canvas?
Anropa ctx.createLinearGradient(x0, y0, x1, y1), lägg till färger med addColorStop(offset, colour), sätt ctx.fillStyle till gradienten och rita en form som fillRect.
Vad är skillnaden mellan createLinearGradient och CSS linear-gradient?
Canvas använder en startpunkt och en slutpunkt i pixlar, medan CSS använder en vinkel och sträcker gradienten över elementet. En liten hjälpfunktion kan omvandla en CSS-vinkel till punkter i canvas.
Kan jag använda oklch- eller hsl-färger i addColorStop?
Ja. addColorStop accepterar vilken CSS-färgsträng som helst som webbläsaren förstår, inklusive hex, rgb(), hsl() och, i aktuella webbläsare, oklch().
Varför visar min gradient i canvas bara en färg?
Gradienten är placerad i canvaskoordinater, så en form som ritas utanför dess start- och slutpunkter får bara närmaste ändfärg. Skapa gradienten utifrån formens position och storlek.
Hur animerar jag en gradient i canvas?
Skapa en ny gradient i varje animationsruta med uppdaterade stopp eller koordinater och rita om. Stoppen i en gradient kan inte flyttas eller tas bort när de är tillagda.
Skriven av Gradiently
Teamet bakom Gradiently, ett designverktyg byggt kring Marks: levande gradienter som får allt du gör att kännas som ditt.
Se vår profil