# HTML canvas-gradient: createLinearGradient, radial og konisk

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

Canvas-gradienter tager koordinater, hvor CSS tager vinkler, og netop den forskel skaber det meste af forvirringen. Her er hver gradientmetode med kode, der kører, og en hjælpefunktion, der omsætter en CSS-vinkel til canvas-punkter.

## The short version

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

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.

```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 mindste fungerende canvas-gradient: en diagonal fra det øverste venstre hjørne til det nederste højre.

## De tre gradientmetoder

| Metode | Argumenter | CSS-ækvivalent |
| --- | --- | --- |
| `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 til 1, `farve` | Et farvestop med en procent |

Hver metode returnerer et CanvasGradient. Du kan gemme det i en variabel og genbruge det til så mange former, du vil.

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](https://gradiently.design/da/guide/css-linear-gradient) tegnes identisk på 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 peger 0deg opad, og vinklerne drejer med uret. Længdeformlen får hjørnerne til at ramme præcis den første og den sidste farve, som i CSS.

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

Det, hjælpefunktionen ovenfor tegner på et canvas på 1200×630, størrelsen på et [Open Graph-billede](https://gradiently.design/da/guide/open-graph-tags). Ser dine vinkler forkerte ud, forklarer [gradientvinkel](https://gradiently.design/da/guide/gradient-angle), hvordan CSS måler dem.

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

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

Når det sidste stop toner ud til gennemsigtigt, kan du stable flere lys på én bund, og sådan bygges lagdelte baggrunde.

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

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

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

At gentage den første farve ved offset 1 skjuler sømmen. createConicGradient virker i aktuelle Chrome, Edge, Safari og 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 eksempler fra denne artikel, vist som deres CSS-tvillinger. [CSS koniske gradienter](https://gradiently.design/da/guide/css-conic-gradient) gennemgår den koniske version mere dybdegående.

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

```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 ikke flytte eller fjerne et stop, når det er tilføjet, så animér ved at oprette en ny gradient i hver frame. Sæt løkken på pause for brugere, der foretrækker reduceret bevægelse.

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

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

Download det færdige canvas som en PNG. På en server kører den samme tegnekode med et canvas-bibliotek til Node.

## 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
- `IndexSizeError` fra addColorStop
- Den koniske gradient starter det forkerte sted

### Løsning

- Gang canvas’ bredde og højde med `devicePixelRatio`, og skalér derefter tilbage med `ctx.scale()`
- Opret gradienten med formens koordinater og ikke canvas’
- Læg lidt støj over, se [gradientbånd](https://gradiently.design/da/guide/gradient-banding)
- Hold offsets mellem 0 og 1
- Start ved `-Math.PI / 2` for at matche CSS

> **Bredere farve på egnede skærme** Chrome og Safari accepterer `canvas.getContext('2d', { colorSpace: 'display-p3' })`, som lader stærke gradienter bruge det bredere P3-område. Browsere, der ikke understøtter det, falder tilbage til sRGB.

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

## FAQ

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