# Gradient i HTML canvas: createLinearGradient, radiell och konisk

[Canonical HTML page](https://gradiently.design/sv/guide/canvas-gradient)

Gradienter i canvas tar koordinater där CSS tar vinklar, och just den skillnaden orsakar det mesta av förvirringen. Här är varje gradientmetod med kod som fungerar, och en hjälpfunktion som gör om en CSS-vinkel till punkter i canvas.

## The short version

- 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.

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.

```js
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)
```

Den minsta fungerande gradienten i canvas: en diagonal från det övre vänstra hörnet till det nedre högra.

## De tre gradientmetoderna

| Metod | Argument | CSS-motsvarighet |
| --- | --- | --- |
| `createLinearGradient` | `x0, y0, x1, y1` | `linear-gradient()` |
| `createRadialGradient` | `x0, y0, r0, x1, y1, r1` | `radial-gradient()` |
| `createConicGradient` | `startAngle, x, y` | `conic-gradient()` |
| `addColorStop` | `offset` 0 till 1, `colour` | Ett färgstopp med procent |

Varje metod returnerar ett CanvasGradient. Du kan spara det i en variabel och återanvända det för hur många former du vill.

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](https://gradiently.design/sv/guide/css-linear-gradient) återges identiskt i canvas.

```js
// 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)
```

I CSS pekar 0deg uppåt och vinklar vrids medurs. Längdformeln gör att hörnen landar exakt på första och sista färgen, som i CSS.

Samma gradient i CSS: `linear-gradient(135deg, #0f172a 0%, #0d9488 100%)`

Vad hjälpfunktionen ovan ritar på en canvas på 1200×630, storleken på en [Open Graph-bild](https://gradiently.design/sv/guide/open-graph-tags). Om dina vinklar ser fel ut förklarar [gradientvinkel](https://gradiently.design/sv/guide/gradient-angle) hur CSS mäter dem.

## 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.

```js
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)
```

Om du låter sista stoppet tona till genomskinligt kan du stapla flera ljus på en botten, så byggs lagrade bakgrunder.

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](https://gradiently.design/sv/guide/css-radial-gradient).

## 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`.

```js
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()
```

Om du upprepar första färgen vid offset 1 döljs skarven. createConicGradient fungerar i aktuella Chrome, Edge, Safari och Firefox.

- createLinearGradient: `linear-gradient(135deg, #1e1b4b 0%, #7c3aed 55%, #f472b6 100%)`
- createRadialGradient: `radial-gradient(circle at 75% 20%, #7c3aed 0%, #2e1065 30%, #0c0a1d 60%)`
- createConicGradient: `conic-gradient(from 0deg, #22d3ee, #7c3aed, #f472b6, #22d3ee)`

De tre exemplen från den här artikeln, visade som sina CSS-tvillingar. [Koniska gradienter i CSS](https://gradiently.design/sv/guide/css-conic-gradient) går djupare in på den koniska varianten.

## 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.

```js
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)
```

Du kan inte flytta eller ta bort ett stopp när det är tillagt, så animera genom att skapa en ny gradient varje bildruta. Pausa loopen för användare som föredrar minskad rörelse.

## 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](https://gradiently.design/sv/guide/png-vs-jpeg) 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.

```js
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')
```

Ladda ner den färdiga canvasen som PNG. På en server körs samma ritkod med ett canvasbibliotek för Node.

## 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
- `IndexSizeError` från addColorStop
- Den koniska gradienten startar på fel ställe

### Lösning

- Multiplicera canvasens bredd och höjd med `devicePixelRatio` och skala sedan tillbaka med `ctx.scale()`
- Skapa gradienten med formens koordinater, inte canvasens
- Lägg lite brus ovanpå, se [gradientbandning](https://gradiently.design/sv/guide/gradient-banding)
- Håll förskjutningarna mellan 0 och 1
- Starta vid `-Math.PI / 2` för att matcha CSS

> **Bredare färg på kapabla skärmar** Chrome och Safari accepterar `canvas.getContext('2d', { colorSpace: 'display-p3' })`, vilket låter klara gradienter använda det bredare P3-området. Webbläsare som inte stöder det faller tillbaka på sRGB.

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](https://gradiently.design/sv/guide/shader-gradients). 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.

## FAQ

### 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.
