UtilAdded in v15Updated in v16Optional

wrResolveCssColor

Resolves a CSS colour, such as a var() or light-dark(), to a value a canvas can paint with.

Usage

Call it in the browser, from afterNextRender, with the element you draw on, the expression and a fallback.

import { Component, ElementRef, afterNextRender, viewChild } from '@angular/core';
import { wrResolveCssColor } from 'ngwr/utils';

@Component({
  selector: 'app-swatch',
  template: '<canvas #canvas width="240" height="48"></canvas>',
})
export class Swatch {
  private readonly canvas = viewChild.required<ElementRef<HTMLCanvasElement>>('canvas');

  constructor() {
    afterNextRender(() => {
      const canvas = this.canvas().nativeElement;
      const ctx = canvas.getContext('2d');
      if (!ctx) return;

      ctx.fillStyle = wrResolveCssColor(canvas, 'var(--wr-color-primary)', '#3969e2');
      ctx.fillRect(0, 0, canvas.width, canvas.height);
    });
  }
}
wrResolveCssColor(canvas, '#3969e2', '#000');
// 'rgb(57, 105, 226)'

wrResolveCssColor(canvas, 'light-dark(#ffffff, #0b1120)', '#fff');
// whichever side is in effect on the canvas

wrResolveCssColor(canvas, 'color-mix(in srgb, var(--wr-color-primary) 20%, transparent)', '#0000');
// 'color(srgb … / 0.2)'

wrResolveCssColor(canvas, 'var(--not-set-anywhere)', '#0f172a');
// '#0f172a' — the fallback

As channels

A WebGL uniform takes numbers. wrResolveCssColorChannels() resolves the same way and returns 0–1 sRGB channels with the alpha dropped, and [0, 0, 0] when even the fallback cannot be read, so a uniform never receives NaN.

import { wrResolveCssColorChannels } from 'ngwr/utils';

const [r, g, b] = wrResolveCssColorChannels(canvas, 'var(--wr-color-primary)', '#3969e2');
gl.uniform3f(tint, r, g, b);

wrResolveCssColorChannels(canvas, 'oklch(0.7 0.15 250)', '#000');
// another colour space is mixed into sRGB first

wrResolveCssColorChannels(canvas, 'not-a-colour', 'neither-is-this');
// [0, 0, 0]

Redraw on a scheme switch

A resolved colour is a snapshot. wrWatchColorScheme() calls back when the page's colour scheme changes, so a still canvas can draw again.

import { afterNextRender } from '@angular/core';
import { wrResolveCssColor, wrWatchColorScheme } from 'ngwr/utils';

constructor() {
  afterNextRender(() => this.draw());
  // A canvas keeps the pixels it was given: draw again when the scheme switches.
  wrWatchColorScheme(() => this.draw());
}

API

NameDescriptionTypeDefault
wrResolveCssColor(context, expression, fallback)Resolves expression against context to rgb(), rgba() or, for a mix, color(srgb …). Returns fallback when it does not parse, or is a lone var() whose property holds no colour or, with no fallback of its own, is not set.(context: Element, expression: string, fallback: string) => string—
wrResolveCssColorChannels(context, expression, fallback)Resolves expression against context to 0–1 sRGB channels with the alpha dropped. Reads fallback, a literal colour, when it cannot, and returns [0, 0, 0] when that cannot be read either.(context: Element, expression: string, fallback: string) => [number, number, number]—
wrWatchColorScheme(callback, options?)Calls callback when the scheme <html> resolves to changes: WrTheme's inline color-scheme, a class or attribute on <html>, or the OS preference under light dark. Stops on destroy; returns a stop function. Does nothing on the server.(callback: (scheme: WrColorScheme) => void, options?: { injector?: Injector }) => () => void—

See also