Die Kurzfassung
- Ein HTML Canvas Farbverlauf ist ein CanvasGradient-Objekt, das mit createLinearGradient, createRadialGradient oder createConicGradient erzeugt, mit addColorStop mit Farbstopps versehen und fillStyle oder strokeStyle zugewiesen wird.
- Canvas-Verläufe nutzen Koordinaten im Canvas-Raum statt Winkeln oder Prozentwerten, also braucht ein linearer Verlauf einen Start- und einen Endpunkt.
- Offsets der Farbstopps reichen von 0 bis 1, und jeder CSS-Farbstring wird akzeptiert, in aktuellen Browsern auch Hex, rgb(), hsl() und oklch().
- createConicGradient beginnt seinen Umlauf an einer nach rechts zeigenden Linie und misst den Winkel in Radiant, anders als CSS conic-gradient, das oben in Grad beginnt.
- Auf Bildschirmen mit hoher Pixeldichte musst du den Canvas-Puffer mit devicePixelRatio skalieren, sonst wirken Verläufe und Text weich.
Auf dieser Seite
Ein HTML Canvas Farbverlauf braucht drei Schritte: ein Verlaufsobjekt mit ctx.createLinearGradient(), createRadialGradient() oder createConicGradient() erzeugen, Farben mit addColorStop(offset, colour) hinzufügen, dann ctx.fillStyle zuweisen und zeichnen. Anders als in CSS wird ein Canvas-Verlauf durch Punkte in Pixeln definiert, du sagst ihm also genau, wo die Farbe beginnt und endet. Alles, was du mit dieser Füllung malst, übernimmt den Teil des Verlaufs, der darunter liegt.
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)Die drei Verlaufsmethoden
createLinearGradientArgumente
x0, y0, x1, y1CSS-Entsprechung
linear-gradient()createRadialGradientArgumente
x0, y0, r0, x1, y1, r1CSS-Entsprechung
radial-gradient()createConicGradientArgumente
startAngle, x, yCSS-Entsprechung
conic-gradient()addColorStopArgumente
offset 0 bis 1, colourCSS-Entsprechung
Der Verlauf ist am Canvas befestigt, nicht an der Form. Erzeugst du einen Verlauf von 0 bis 400 und füllst dann ein kleines Quadrat bei x 300, zeigt das Quadrat nur das pinke Ende. Das überrascht alle, die von CSS kommen, wo sich ein Verlauf immer auf das Element dehnt. Erzeuge den Verlauf mit den Koordinaten der Form selbst, wenn er passen soll.
createLinearGradient und CSS-Winkel
In CSS schreibst du 135deg. Canvas will zwei Punkte. Diese Hilfsfunktion rechnet einen CSS-Winkel in dieselben Start- und Endpunkte um, die CSS verwendet, sodass ein als CSS linear-gradient geschriebenes Design auf dem Canvas identisch aussieht.
// 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
Ein radialer Verlauf auf dem Canvas wird durch zwei Kreise definiert: einen Startkreis und einen Endkreis. Farbstopp 0 liegt auf dem ersten Kreis, Stopp 1 auf dem zweiten. Meist soll der erste Kreis ein Punkt sein, sein Radius ist also 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)Verschiebst du den Mittelpunkt des ersten Kreises weg vom zweiten, kippt das Licht, wie ein Spot, der schräg auf eine Wand fällt. CSS hat für diesen Versatz keine direkte Entsprechung. Für die CSS-Seite siehe radiale Farbverläufe in CSS.
createConicGradient
createConicGradient(startAngle, x, y) lässt Farbe um einen Mittelpunkt kreisen. Zwei Details unterscheiden sich von CSS: Der Winkel ist in Radiant, und 0 zeigt nach rechts (drei Uhr), nicht nach oben. Um ein CSS conic-gradient(from 0deg, ...) nachzubilden, beginne bei -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()Verlaufstext, Konturen und Animation
fillStyle und strokeStyle akzeptieren beide einen Verlauf, also funktionieren Text und Konturen genauso. Leg den Verlauf über den eigenen Kasten des Textes, gemessen mit measureText(), damit die ganze Farbskala innerhalb der Buchstaben erscheint.
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)Den Canvas als Bild speichern
Ein häufiger Grund, Verläufe auf einen Canvas zu zeichnen, ist das Erzeugen eines Bildes: eine Share-Karte, ein Zertifikat, ein Cover. Ruf canvas.toBlob() mit image/png für Verläufe und Text auf, weil PNG weiche Übergänge intakt hält, und nimm JPEG nur, wenn das Bild überwiegend Foto ist. PNG vs. JPG erklärt den Unterschied. Zeichne in der echten Ausgabegröße, etwa 1200×630 für eine Linkvorschau, statt einen kleinen Canvas hochzuskalieren.
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')Häufige Probleme mit Canvas-Verläufen
Symptom
- Der Verlauf wirkt auf dem Handy unscharf
- In einer Form erscheint nur eine Farbe
- Sichtbare Streifen in einem dunklen Verlauf
IndexSizeErrorvon addColorStop- Der konische Verlauf beginnt an der falschen Stelle
Lösung
- Breite und Höhe des Canvas mit
devicePixelRatiomultiplizieren, dann mitctx.scale()zurückskalieren - Den Verlauf mit den Koordinaten der Form erzeugen, nicht mit denen des Canvas
- Leichtes Rauschen darüberlegen, siehe Streifenbildung in Farbverläufen
- Offsets zwischen 0 und 1 halten
- Bei
-Math.PI / 2beginnen, um CSS zu entsprechen
Wenn du Verläufe brauchst, die sich mit echtem Licht bewegen statt flacher Übergänge, stößt ein Canvas an seine Grenzen und WebGL übernimmt, beschrieben in Shader-Farbverläufe. Und wenn der Canvas nur Mittel zum Bild ist, etwa für eine Social-Media-Karte oder ein Poster, rendert Gradiently einen Mark in jeder Größe von 200 bis 8.000 px mit fertig angeordneten Wörtern, sodass du keinen Zeichencode pflegen musst.
Häufige Fragen
Wie erstelle ich einen Farbverlauf auf einem HTML Canvas?
Ruf ctx.createLinearGradient(x0, y0, x1, y1) auf, füge Farben mit addColorStop(offset, colour) hinzu, setz ctx.fillStyle auf den Verlauf und zeichne eine Form wie fillRect.
Was ist der Unterschied zwischen createLinearGradient und CSS linear-gradient?
Canvas nutzt einen Start- und einen Endpunkt in Pixeln, CSS einen Winkel und dehnt den Verlauf auf das Element. Eine kleine Hilfsfunktion kann einen CSS-Winkel in Canvas-Punkte umrechnen.
Kann ich oklch- oder hsl-Farben in addColorStop verwenden?
Ja. addColorStop akzeptiert jeden CSS-Farbstring, den der Browser versteht, darunter Hex, rgb(), hsl() und in aktuellen Browsern oklch().
Warum zeigt mein Canvas-Verlauf nur eine Farbe?
Der Verlauf ist in Canvas-Koordinaten positioniert, also bekommt eine Form außerhalb seiner Start- und Endpunkte nur die nächstgelegene Endfarbe. Erzeuge den Verlauf mit Position und Größe der Form.
Wie animiere ich einen Canvas-Verlauf?
Erzeuge in jedem Animationsframe einen neuen Verlauf mit aktualisierten Stopps oder Koordinaten und zeichne neu. Die Stopps eines Verlaufs lassen sich nach dem Hinzufügen weder verschieben noch entfernen.
Geschrieben von Gradiently
Das Team hinter Gradiently, einem Designtool rund um Marks: lebendige Farbverläufe, durch die alles, was du gestaltest, nach dir aussieht.
Unser Profil ansehen