De korte versie
- Een HTML canvas kleurverloop is een CanvasGradient-object, gemaakt met createLinearGradient, createRadialGradient of createConicGradient, voorzien van kleurstops met addColorStop en toegewezen aan fillStyle of strokeStyle.
- Canvas-verlopen gebruiken coördinaten in de canvasruimte, geen hoeken of percentages, dus een lineair verloop heeft een beginpunt en een eindpunt nodig.
- Offsets van kleurstops lopen van 0 tot 1 en elke CSS-kleurtekst is toegestaan, ook hex, rgb(), hsl() en in actuele browsers oklch().
- createConicGradient begint zijn draai bij een lijn die naar rechts wijst en meet de hoek in radialen, anders dan CSS conic-gradient, dat bovenaan begint en graden gebruikt.
- Maak op schermen met hoge dichtheid de canvasbuffer groter met devicePixelRatio, anders ogen verlopen en tekst wazig.
Op deze pagina
Een HTML canvas kleurverloop vraagt drie stappen: maak een verloopobject met ctx.createLinearGradient(), createRadialGradient() of createConicGradient(), voeg kleuren toe met addColorStop(offset, kleur) en wijs het toe aan ctx.fillStyle om te tekenen. Anders dan in CSS wordt een canvas-verloop bepaald door punten in pixels, dus je geeft precies aan waar de kleur begint en eindigt. Alles wat je met die vulling schildert, pakt het deel van het verloop dat eronder ligt.
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 drie verloopmethodes
createLinearGradientArgumenten
x0, y0, x1, y1CSS-equivalent
linear-gradient()createRadialGradientArgumenten
x0, y0, r0, x1, y1, r1CSS-equivalent
radial-gradient()createConicGradientArgumenten
startAngle, x, yCSS-equivalent
conic-gradient()addColorStopArgumenten
offset 0 tot 1, kleurCSS-equivalent
Het verloop zit vast aan het canvas, niet aan de vorm. Maak je een verloop van 0 tot 400 en vul je daarna een klein vierkant op x 300, dan zie je in het vierkant alleen het roze uiteinde. Dat verrast mensen die uit CSS komen, waar een verloop altijd over het hele element loopt. Maak het verloop met de eigen coördinaten van de vorm als je wilt dat het past.
createLinearGradient en CSS-hoeken
In CSS schrijf je 135deg. Canvas wil twee punten. Deze helper zet een CSS-hoek om in dezelfde begin- en eindpunten die CSS gebruikt, zodat een ontwerp dat is geschreven als CSS lineair verloop op canvas er identiek uitziet.
// 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
Een radiaal verloop op canvas wordt bepaald door twee cirkels: een begincirkel en een eindcirkel. Kleurstop 0 ligt op de eerste cirkel en stop 1 op de tweede. Meestal wil je dat de eerste cirkel een punt is, dus met straal 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)Schuif het middelpunt van de eerste cirkel weg van dat van de tweede en het licht kantelt, als een spot die schuin op een muur valt. CSS heeft daar geen directe tegenhanger voor. Voor de CSS-kant, zie CSS radiale verlopen.
createConicGradient
createConicGradient(startAngle, x, y) laat kleur rond een middelpunt draaien. Twee dingen verschillen van CSS: de hoek is in radialen en 0 wijst naar rechts (drie uur), niet naar boven. Om een CSS conic-gradient(from 0deg, ...) na te bootsen begin je bij -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()Verlooptekst, lijnen en animatie
fillStyle en strokeStyle accepteren allebei een verloop, dus tekst en omtrekken werken op dezelfde manier. Zet het verloop over het eigen vak van de tekst, gemeten met measureText(), zodat het volledige kleurbereik in de letters verschijnt.
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)Het canvas als afbeelding opslaan
Een veelvoorkomende reden om verlopen op canvas te tekenen is het genereren van een afbeelding: een deelkaart, een certificaat, een cover. Roep canvas.toBlob() aan met image/png voor verlopen en tekst, want PNG houdt vloeiende overgangen intact, en gebruik JPEG alleen als de afbeelding vooral een foto is. PNG of JPG legt de afweging uit. Teken op het echte uitvoerformaat, zoals 1200×630 voor een linkvoorbeeld, in plaats van een klein canvas op te schalen.
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')Veelvoorkomende problemen met canvas-verlopen
Symptoom
- Verloop ziet er wazig uit op een telefoon
- In een vorm zie je maar één kleur
- Zichtbare strepen in een donker verloop
IndexSizeErrorvan addColorStop- Conisch verloop begint op de verkeerde plek
Oplossing
- Vermenigvuldig breedte en hoogte van het canvas met
devicePixelRatioen schaal metctx.scale()terug - Maak het verloop met de coördinaten van de vorm, niet van het canvas
- Leg lichte ruis eroverheen, zie kleurverloop banding
- Houd offsets tussen 0 en 1
- Begin bij
-Math.PI / 2om CSS te evenaren
Heb je verlopen nodig die meebewegen met echt licht in plaats van vlakke overgangen, dan bereikt een canvas zijn grenzen en neemt WebGL het over, zie shader-verlopen. En als het canvas slechts een middel is voor een afbeelding, zoals een social kaart of poster, rendert Gradiently een Mark op elk formaat van 200 tot 8.000 px met de woorden al netjes gezet, zodat er geen tekencode te onderhouden valt.
Vragen die mensen stellen
Hoe maak ik een kleurverloop op een HTML canvas?
Roep ctx.createLinearGradient(x0, y0, x1, y1) aan, voeg kleuren toe met addColorStop(offset, kleur), zet ctx.fillStyle op het verloop en teken een vorm zoals fillRect.
Wat is het verschil tussen createLinearGradient en CSS linear-gradient?
Canvas gebruikt een beginpunt en een eindpunt in pixels, CSS gebruikt een hoek en rekt het verloop uit over het element. Een kleine helper kan een CSS-hoek omzetten in canvaspunten.
Kan ik oklch- of hsl-kleuren gebruiken in addColorStop?
Ja. addColorStop accepteert elke CSS-kleurtekst die de browser begrijpt, ook hex, rgb(), hsl() en in actuele browsers oklch().
Waarom toont mijn canvas-verloop maar één kleur?
Het verloop ligt vast in canvascoördinaten, dus een vorm buiten het begin- en eindpunt krijgt alleen de dichtstbijzijnde eindkleur. Maak het verloop met de positie en grootte van de vorm.
Hoe animeer ik een canvas-verloop?
Maak bij elk animatieframe een nieuw verloop met bijgewerkte stops of coördinaten en teken opnieuw. Stops van een verloop kunnen na toevoeging niet worden verplaatst of verwijderd.
Geschreven door Gradiently
Het team achter Gradiently, een ontwerptool rond Marks: levende kleurverlopen die alles wat je ontwerpt op jou laten lijken.
Bekijk ons profiel