Color

The SDK's color parser and converter. Every color prop (UI styles, sprite.color, material colors) already takes a ColorInput and converts it itself; reach for Color when you need a numeric form yourself — floats to blend by hand, a packed int for a shader uniform, a hex string.

  • know which color formats a color prop accepts (hex, rgb(), hsl(), names, arrays)
  • convert a css color string to 0..1 floats
  • pack a color into an 0xRRGGBB int for a shader or a material
  • turn any color into a '#rrggbbaa' hex string
  • check whether a string is a valid color without throwing
  • blend two colors by hand

At a glance

TypeScript
const badge = UIColumn().style({ bgColor: '#e33', borderColor: 'rgb(255 51 51 / 50%)' })  // any ColorInput works on a color prop

const [r, g, b] = Color.toRgb01('#10131a')       // [0.062…, 0.074…, 0.101…]
const packed = Color.toPackedRgb([1, 0.5, 0])    // 0xff8000
const css = Color.toHexString(0xff8000)          // '#ff8000ff'

Color formats you can pass: ColorInput

TypeScript
'#e33'  '#e33c'                    // hex shorthand — #rgb / #rgba, nibbles doubled
'#ff3333'  '#ff3333cc'             // hex — #rrggbb / #rrggbbaa (the '#' is required)
'rgb(255, 51, 51)'  'rgba(255 51 51 / 80%)'   // rgb() / rgba(), comma or space syntax
'hsl(0, 100%, 60%)'  'hsla(0 100% 60% / .5)'  // hsl() / hsla(); hue units deg / rad / grad / turn
'red'  'RebeccaPurple'             // the 148 CSS color names, case-insensitive (green = #008000)
'transparent'  'clear'             // (0,0,0,0) — `clear` is the one non-CSS alias
0xff3333                           // packed 0xRRGGBB int — alpha is always 1
[1, 0.2, 0.2]                      // [r, g, b] floats, 0..1
[1, 0.2, 0.2, 0.8]                 // [r, g, b, a] floats, 0..1

The string parser is the one every engine uses (AnyCanvas's CSS color parser), so a color means the same bytes in the SDK, the UI, SVG and the canvas.

Note

anything else throws with the value: a string that is not a CSS color ('nope', 'ff3333' without the #), an array that is not 3 or 4 finite numbers, a number that is not an integer in 0..0xFFFFFF. Probe without throwing with Color.tryParse.

Note

a packed input int carries no alpha — 0xff3333cc throws instead of guessing between RGB and RGBA. To pass alpha, use a string ('#ff3333cc') or a 4-element array.

Convert a color to floats, a packed int or a hex string

TypeScript
Color.toRgb01(c): [r, g, b]              // floats 0..1 (alpha dropped)
Color.toRgba01(c): [r, g, b, a]          // floats 0..1; float-array inputs pass through losslessly
Color.toPackedRgb(c): number             // 0xRRGGBB
Color.toPackedRgba(c): number            // 0xRRGGBBAA, unsigned (safe to compare/shift)
Color.toHexString(c): string             // '#rrggbbaa', always eight lower-case digits

Bytes round half up from float32 (0.5 → 0x80), the rule of every engine, so Color.toHexString matches what the UI engine and the canvas make of the same string.

Check whether a string is a valid color: Color.tryParse

To test a value (user input, a config entry) before using it as a color, tryParse returns its floats or null — it never throws.

TypeScript
Color.tryParse(c): [r, g, b, a] | null   // floats 0..1, or null when c is not a color
TypeScript
const input = 'RebeccaPurple'                    // e.g. typed by the user
const rgba = Color.tryParse(input)               // null instead of a throw
if (rgba) console.log('a color, alpha', rgba[3])
else console.log('not a color:', input)

Blend two colors by hand

Pull both colors out as floats, mix the channels with Mathf.lerp, and convert back:

TypeScript
const a = Color.toRgba01('#ff3333')
const b = Color.toRgba01('rgb(51 102 255)')
const t = 0.25                                   // 0 = a, 1 = b
const mixed = Color.toHexString([
  Mathf.lerp(a[0], b[0], t), Mathf.lerp(a[1], b[1], t), Mathf.lerp(a[2], b[2], t), Mathf.lerp(a[3], b[3], t),
])
console.log(mixed)                               // '#cc4066ff'

See also

  • Conventions — where ColorInput is accepted
  • Mathf — lerp / clamp01 for blending channels you've pulled out with toRgba01