# HTML canvas-gradient: lineær, radial og konisk

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

Canvas-gradienter bruker koordinater der CSS bruker vinkler, og denne forskjellen skaper mest forvirring. Her får du alle metodene med fungerende kode og en hjelpefunksjon som gjør en CSS-vinkel om til punkter på canvas.

## The short version

- En HTML canvas-gradient er et CanvasGradient-objekt laget med createLinearGradient, createRadialGradient eller createConicGradient, med fargestopp fra addColorStop og tilordnet fillStyle eller strokeStyle.
- Canvas-gradienter bruker koordinater i canvas, ikke vinkler eller prosent, så en lineær gradient trenger et startpunkt og et sluttpunkt.
- Posisjonene til fargestoppene går fra 0 til 1, og alle CSS-fargestrenger godtas, blant annet hex, rgb(), hsl() og oklch() i dagens nettlesere.
- createConicGradient starter fra en linje mot høyre og måler vinkelen i radianer, mens CSS conic-gradient starter øverst og bruker grader.
- På skjermer med høy pikseltetthet må canvas-bufferen dimensjoneres med devicePixelRatio, ellers blir gradienter og tekst uskarpe.

En **HTML canvas-gradient** lages i tre trinn: lag et gradientobjekt med `ctx.createLinearGradient()`, `createRadialGradient()` eller `createConicGradient()`, legg til farger med `addColorStop(offset, colour)`, tilordne det til `ctx.fillStyle` og tegn. I motsetning til CSS defineres en canvas-gradient med punkter i piksler, så du angir nøyaktig hvor fargen begynner og slutter. Alt du maler med dette fyllet, får den delen 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 enkleste fungerende canvas-gradienten: diagonalt fra øvre venstre til nedre høyre hjørne.

## De tre gradientmetodene

| Metode | Argumenter | Tilsvarende CSS |
| --- | --- | --- |
| `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, `colour` | Et fargestopp med en prosentverdi |

Hver metode returnerer en CanvasGradient. Du kan lagre den i en variabel og bruke den igjen til så mange former du vil.

Gradienten er knyttet til canvas, ikke formen. Lager du en gradient fra 0 til 400 og fyller en liten firkant ved x 300, viser firkanten bare den rosa enden. Det overrasker dem som kommer fra CSS, der gradienten alltid strekkes til elementet. Bruk formens egne koordinater når gradienten skal passe i den.

## createLinearGradient og CSS-vinkler

I CSS kan du skrive `135deg`. Canvas trenger to punkter. Denne hjelpefunksjonen gjør en CSS-vinkel om til de samme start- og sluttpunktene som CSS bruker, slik at et design skrevet som en [lineær CSS-gradient](https://gradiently.design/nb/guide/css-linear-gradient) gjengis likt 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 peker 0deg oppover, og vinklene går med klokken. Lengdeformelen plasserer hjørnene nøyaktig på den første og siste fargen, slik CSS gjør.

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

Dette tegner hjelpefunksjonen på et canvas på 1200×630, størrelsen på et [Open Graph-bilde](https://gradiently.design/nb/guide/open-graph-tags). Ser vinklene feil ut, forklarer [gradientvinkler](https://gradiently.design/nb/guide/gradient-angle) hvordan CSS måler dem.

## createRadialGradient

En radial gradient på canvas defineres av to sirkler: en startsirkel og en sluttsirkel. Fargestopp 0 ligger på den første, og stopp 1 på den andre. Som regel bør den første sirkelen være et punkt, med radius 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 siste stopp tones ut til gjennomsiktig, kan du legge flere lys oppå samme bunn. Slik bygges bakgrunner med flere lag.

Flytt sentrum av den første sirkelen bort fra den andre, så vinkles lyset som en lyskaster som treffer en vegg på skrå. CSS har ingen direkte motsvarighet til denne forskyvningen. For CSS-versjonen, se [radiale CSS-gradienter](https://gradiently.design/nb/guide/css-radial-gradient).

## createConicGradient

`createConicGradient(startAngle, x, y)` fordeler farge rundt et midtpunkt. To detaljer skiller seg fra CSS: vinkelen er i radianer, og 0 peker mot høyre, klokken tre, ikke oppover. For å matche CSS `conic-gradient(from 0deg, ...)`, start 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()
```

Gjenta den første fargen ved posisjon 1 for å skjule skjøten. createConicGradient virker i dagens 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 eksemplene i artikkelen vist som tilsvarende CSS-gradienter. [Koniske CSS-gradienter](https://gradiently.design/nb/guide/css-conic-gradient) går dypere inn i den koniske varianten.

## Gradienttekst, konturer og animasjon

Både `fillStyle` og `strokeStyle` godtar en gradient, så tekst og konturer fungerer likt. Legg gradienten over tekstens egen boks, målt med `measureText()`, slik at hele fargespekteret vises inni bokstavene.

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

Et stopp kan ikke flyttes eller fjernes etter at det er lagt til. Animer derfor ved å lage en ny gradient for hver bilderamme. Sett løkken på pause for brukere som foretrekker redusert bevegelse.

## Lagre canvas som et bilde

En vanlig grunn til å tegne gradienter på canvas er å lage et bilde: et delingskort, et sertifikat eller et omslag. Bruk `canvas.toBlob()` med `image/png` for gradienter og tekst, fordi PNG bevarer myke overganger. Bruk JPEG bare når bildet hovedsakelig er et foto. [PNG mot JPG](https://gradiently.design/nb/guide/png-vs-jpeg) forklarer avveiningen. Tegn i den faktiske størrelsen, for eksempel 1200×630 for en lenkeforhåndsvisning, fremfor å forstørre et lite 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')
```

Last ned det ferdige canvas som PNG. På en server kjører samme tegnekode med et canvas-bibliotek for Node.

## Vanlige problemer med canvas-gradienter

### Symptom

- Gradienten er uskarp på telefonen
- Bare én farge vises i en form
- Synlige striper i en mørk gradient
- `IndexSizeError` fra addColorStop
- Konisk gradient starter på feil sted

### Løsning

- Gang canvas-bredden og høyden med `devicePixelRatio`, og skaler tilbake med `ctx.scale()`
- Lag gradienten med formens koordinater, ikke canvas sine
- Legg lett støy over, se [striper i gradienter](https://gradiently.design/nb/guide/gradient-banding)
- Hold posisjonene mellom 0 og 1
- Start ved `-Math.PI / 2` for å matche CSS

> **Større fargerom på skjermer som støtter det** Chrome og Safari godtar `canvas.getContext('2d', { colorSpace: 'display-p3' })`, slik at sterke gradienter kan bruke det større P3-fargerommet. Nettlesere uten støtte faller tilbake til sRGB.

Når du trenger gradienter som beveger seg med ekte lys fremfor flate overganger, når canvas sin grense og WebGL tar over. Det beskrives i [shader-gradienter](https://gradiently.design/nb/guide/shader-gradients). Når canvas bare brukes for å lage et bilde, for eksempel et innlegg eller en plakat, kan Gradiently gjengi en Mark i alle størrelser fra 200 til 8 000 px og plassere teksten for deg. Da slipper du å vedlikeholde tegnekode.

## FAQ

### Hvordan lager jeg en gradient på et HTML canvas?

Kall `ctx.createLinearGradient(x0, y0, x1, y1)`, legg til farger med `addColorStop(offset, colour)`, sett `ctx.fillStyle` til gradienten og tegn en form, for eksempel med `fillRect`.

### Hva er forskjellen mellom createLinearGradient og CSS linear-gradient?

Canvas bruker et startpunkt og et sluttpunkt i piksler, mens CSS bruker en vinkel og strekker gradienten til elementet. En liten hjelpefunksjon kan gjøre en CSS-vinkel om til canvas-punkter.

### Kan jeg bruke oklch- eller hsl-farger i addColorStop?

Ja. addColorStop godtar alle CSS-fargestrenger nettleseren forstår, blant annet hex, rgb(), hsl() og, i dagens nettlesere, oklch().

### Hvorfor viser canvas-gradienten min bare én farge?

Gradienten plasseres i canvas-koordinater, så en form utenfor start- og sluttpunktene får bare nærmeste endefarge. Lag gradienten med formens plassering og størrelse.

### Hvordan animerer jeg en canvas-gradient?

Lag en ny gradient for hver animasjonsramme med oppdaterte stopp eller koordinater, og tegn på nytt. Fargestopp kan ikke flyttes eller fjernes etter at de er lagt til.
