Kort fortalt
- En HTML canvas-gradient er et CanvasGradient-objekt lavet med createLinearGradient, createRadialGradient eller createConicGradient, tildelt farvestop med addColorStop og sat på fillStyle eller strokeStyle.
- Canvas-gradienter bruger koordinater i canvas-rummet og ikke vinkler eller procenter, så en lineær gradient har brug for et startpunkt og et slutpunkt.
- Farvestoppenes offsets går fra 0 til 1, og enhver CSS-farvestreng accepteres, også hex, rgb(), hsl() og oklch() i aktuelle browsere.
- createConicGradient starter sit sving fra en linje, der peger mod højre, og måler vinklen i radianer, i modsætning til CSS conic-gradient, der starter øverst i grader.
- På skærme med høj tæthed skal du dimensionere canvas-bufferen efter devicePixelRatio, ellers ser gradienter og tekst bløde ud.
På denne side
En HTML canvas-gradient tager tre trin: Opret et gradientobjekt med ctx.createLinearGradient(), createRadialGradient() eller createConicGradient(), tilføj farver med addColorStop(offset, farve), og tildel det så til ctx.fillStyle og tegn. I modsætning til CSS defineres en canvas-gradient af punkter i pixels, så du fortæller præcis, hvor farven starter og slutter. Alt, du maler med den udfyldning, henter den del af gradienten, der ligger nedenunder.
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 gradientmetoder
createLinearGradientArgumenter
x0, y0, x1, y1CSS-ækvivalent
linear-gradient()createRadialGradientArgumenter
x0, y0, r0, x1, y1, r1CSS-ækvivalent
radial-gradient()createConicGradientArgumenter
startAngle, x, yCSS-ækvivalent
conic-gradient()addColorStopArgumenter
offset 0 til 1, farveCSS-ækvivalent
Gradienten er fastlåst til canvas og ikke til formen. Opretter du en gradient fra 0 til 400 og så udfylder et lille kvadrat ved x 300, viser kvadratet kun den lyserøde ende. Det overrasker folk, der kommer fra CSS, hvor en gradient altid strækker sig til elementet. Opret gradienten med formens egne koordinater, når du vil have, at den passer.
createLinearGradient og CSS-vinkler
I CSS kan du skrive 135deg. Canvas vil have to punkter. Denne hjælpefunktion omsætter en CSS-vinkel til de samme start- og slutpunkter, som CSS bruger, så et design skrevet som en CSS lineær gradient tegnes identisk på 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 radial gradient på canvas defineres af to cirkler: en startcirkel og en slutcirkel. Farvestop 0 ligger på den første cirkel og stop 1 på den anden. For det meste vil du have, at den første cirkel er et punkt, så dens radius er 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)Flyt centrum af den første cirkel væk fra den anden, og lyset hælder, som en projektør, der rammer en væg på skrå. CSS har ingen direkte ækvivalent til den forskydning. Til CSS-siden, se CSS radiale gradienter.
createConicGradient
createConicGradient(startAngle, x, y) fejer farve rundt om et centrumpunkt. To detaljer adskiller sig fra CSS: Vinklen er i radianer, og 0 peger mod højre (klokken tre) og ikke opad. For at matche en CSS conic-gradient(from 0deg, ...) skal du starte ved -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()Gradienttekst, streger og animation
fillStyle og strokeStyle accepterer begge en gradient, så tekst og konturer virker på samme måde. Sæt gradienten hen over tekstens egen boks, målt med measureText(), så hele farveområdet vises inde i bogstaverne.
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)Gem canvas som et billede
En almindelig grund til at tegne gradienter på canvas er at generere et billede: et delekort, et certifikat, et omslag. Kald canvas.toBlob() med image/png til gradienter og tekst, fordi PNG bevarer bløde overgange intakte, og brug kun JPEG, når billedet mest er et fotografi. PNG mod JPG forklarer afvejningen. Tegn i den reelle outputstørrelse, for eksempel 1200×630 til en linkforhåndsvisning, i stedet for at skalere et lille canvas op.
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')Almindelige problemer med canvas-gradienter
Symptom
- Gradienten ser sløret ud på en telefon
- Kun én farve vises i en form
- Synlige striber i en mørk gradient
IndexSizeErrorfra addColorStop- Den koniske gradient starter det forkerte sted
Løsning
- Gang canvas’ bredde og højde med
devicePixelRatio, og skalér derefter tilbage medctx.scale() - Opret gradienten med formens koordinater og ikke canvas’
- Læg lidt støj over, se gradientbånd
- Hold offsets mellem 0 og 1
- Start ved
-Math.PI / 2for at matche CSS
Når du har brug for gradienter, der bevæger sig med reel belysning frem for flade blandinger, når et canvas sin grænse, og WebGL tager over, hvilket er gennemgået i shader-gradienter. Og når canvas kun er et middel til et billede, som et delekort eller en plakat, tegner Gradiently en Mark i enhver størrelse fra 200 til 8.000 px med ordene lagt ud for dig, så der ikke er nogen tegnekode at vedligeholde.
Spørgsmål, folk stiller
Hvordan laver jeg en gradient på et HTML canvas?
Kald ctx.createLinearGradient(x0, y0, x1, y1), tilføj farver med addColorStop(offset, farve), sæt ctx.fillStyle til gradienten, og tegn en form som fillRect.
Hvad er forskellen på createLinearGradient og CSS linear-gradient?
Canvas bruger et startpunkt og et slutpunkt i pixels, mens CSS bruger en vinkel og strækker gradienten til elementet. En lille hjælpefunktion kan omsætte en CSS-vinkel til canvas-punkter.
Kan jeg bruge oklch- eller hsl-farver i addColorStop?
Ja. addColorStop accepterer enhver CSS-farvestreng, browseren forstår, også hex, rgb(), hsl() og i aktuelle browsere oklch().
Hvorfor viser min canvas-gradient kun én farve?
Gradienten er placeret i canvas-koordinater, så en form tegnet uden for dens start- og slutpunkter kun henter den nærmeste endefarve. Opret gradienten ud fra formens position og størrelse.
Hvordan animerer jeg en canvas-gradient?
Opret en ny gradient i hver animationsframe med opdaterede stop eller koordinater, og tegn igen. En gradients stop kan ikke flyttes eller fjernes, når de er tilføjet.
Skrevet af Gradiently
Holdet bag Gradiently, et designværktøj bygget om Marks: levende gradienter, der får alt, du designer, til at ligne dig.
Se vores profil