| name | pixijs-color |
| description | Use this skill when creating, converting, or manipulating colors in PixiJS v8. Covers Color class input formats (hex, CSS names, RGB/HSL objects, arrays, Uint8Array), conversion methods (toHex, toNumber, toArray, toRgba), component access, setAlpha/multiply/premultiply, Color.shared singleton. Triggers on: Color, ColorSource, hex, rgb, hsl, tint, premultiply, Color.shared, color conversion. |
| license | MIT |
The Color class creates and converts colors for tints, fills, strokes, and anywhere PixiJS accepts a ColorSource. Most APIs accept raw hex/strings directly, so explicit new Color(...) is only needed when converting formats or manipulating values.
Quick Start
const fillColor = new Color("#ff6600");
console.log(fillColor.toHex());
console.log(fillColor.toNumber());
console.log(fillColor.toArray());
const g = new Graphics().rect(0, 0, 200, 100).fill(fillColor);
app.stage.addChild(g);
const sprite = Sprite.from("hero.png");
sprite.tint = "dodgerblue";
app.stage.addChild(sprite);
const t = Color.shared.setValue(0xffffff).multiply([1, 0.5, 0.5]).toNumber();
sprite.tint = t;
Related skills: pixijs-scene-graphics (fill/stroke colors), pixijs-scene-sprite (tint), pixijs-blend-modes (compositing).
Core Patterns
Accepted input formats
import { Color } from "pixi.js";
new Color(0xff0000);
new Color("#ff0000");
new Color("#f00");
new Color("ff0000");
new Color("red");
new Color("dodgerblue");
new Color({ r: 255, g: 0, b: 0 });
new Color({ r: 255, g: 0, b: 0, a: 0.5 });
new Color({ h: 0, s: 100, l: 50 });
new Color({ h: 0, s: 100, l: 50, a: 0.5 });
new Color({ h: 0, s: 100, v: 100 });
new Color("rgb(255, 0, 0)");
new Color("rgba(255, 0, 0, 0.5)");
new Color("hsl(0, 100%, 50%)");
new Color([1, 0, 0]);
new Color([1, 0, 0, 0.5]);
new Color(new Uint8Array([255, 0, 0]));
new Color(new Uint8ClampedArray([255, 0, 0, 128]));
new Color("#ff0000ff");
new Color("#f00f");
const red = new Color("red");
const copy = new Color(red);
Conversion methods
import { Color } from "pixi.js";
const color = new Color("#ff6600");
color.toHex();
color.toHexa();
color.toNumber();
color.toArray();
color.toRgbArray();
color.toRgbaString();
color.toRgba();
color.toRgb();
color.toUint8RgbArray();
color.setValue(0xff0000).toHex();
Component access
import { Color } from "pixi.js";
const color = new Color("rgba(255, 128, 0, 0.8)");
color.red;
color.green;
color.blue;
color.alpha;
All component getters return normalized 0-1 values.
Manipulation
import { Color } from "pixi.js";
const color = new Color("red");
color.setAlpha(0.5);
color.multiply(0x808080);
color.premultiply(0.8);
color.premultiply(0.8, false);
new Color("white").setAlpha(0.5).multiply([0.8, 0.2, 0.2]);
multiply() and premultiply() are destructive; they modify the color and set value to null (original format is lost).
Non-destructive premultiplied output
import { Color } from "pixi.js";
const color = new Color("red").setAlpha(0.5);
const packed = color.toPremultiplied(color.alpha);
const alphaOnly = color.toPremultiplied(color.alpha, false);
toPremultiplied(alpha, applyToRGB?) returns a 32-bit 0xAARRGGBB integer without mutating this. Use it in batchers and tint math where the source color must be reused. When applyToRGB is false, only the alpha byte is packed; the RGB stays at its full value.
Reusing output buffers
import { Color } from "pixi.js";
const rgba = new Float32Array(4);
const rgb = new Float32Array(3);
const rgb8 = new Uint8Array(3);
app.ticker.add(() => {
Color.shared.setValue(sprite.tint).toArray(rgba).toRgbArray(rgb);
Color.shared.toUint8RgbArray(rgb8);
});
toArray(out?), toRgbArray(out?), and toUint8RgbArray(out?) accept a reusable number[], Float32Array, Uint8Array, or Uint8ClampedArray and write into it. Pass your own buffer in hot paths to avoid allocating per frame; omit the argument and the Color instance returns its internal cache array.
Packing for GPU buffers
| Method | Returns |
|---|
toBgrNumber() | 24-bit 0xBBGGRR integer with R/B swapped |
toLittleEndianNumber() | Same 24-bit swap, convenient for little-endian vertex writes |
Both are cheap and useful when emitting colors straight into packed vertex attributes.
Color.shared for temporary operations
import { Color } from "pixi.js";
const hex = Color.shared.setValue("#ff6600").toNumber();
const arr = Color.shared.setValue(0xff0000).toArray();
Color.shared is a singleton that avoids allocating a new Color on every call. This matters in hot paths like render loops or per-frame tint calculations where repeated new Color() creates GC pressure. Do not store references to it; other code may mutate it.
import { Color } from "pixi.js";
app.ticker.add(() => {
const t = performance.now() / 1000;
sprite.tint = Color.shared
.setValue("white")
.multiply([Math.sin(t) * 0.5 + 0.5, 0.2, 0.8])
.toNumber();
});
Validating input
import { Color } from "pixi.js";
Color.isColorLike("red");
Color.isColorLike("#ff0000");
Color.isColorLike(0xff0000);
Color.isColorLike([1, 0, 0]);
Color.isColorLike({ r: 1, g: 0, b: 0 });
Color.isColorLike({ foo: 1 });
Color.isColorLike(null);
Color.isColorLike() checks the structural shape (string, number, array, or recognized object). It doesn't validate that a string is a real CSS color name, nor that array values fall in range. Use it as a type guard before passing user input to new Color() or setValue().
Common Mistakes
[MEDIUM] Expecting toRgba() to return 0-255 values
Wrong:
import { Color } from "pixi.js";
const { r, g, b } = new Color({ r: 255, g: 128, b: 0 }).toRgba();
Correct:
import { Color } from "pixi.js";
const [r, g, b] = new Color({ r: 255, g: 128, b: 0 }).toUint8RgbArray();
RGB object inputs use 0-255 range ({ r: 255, g: 0, b: 0 }), but all output methods (toRgba(), toRgb(), toArray(), toRgbArray()) normalize to 0-1. Use toUint8RgbArray() when you need 0-255 integers for CSS or external APIs.
[MEDIUM] Using 0-255 range in color arrays
Wrong:
import { Color } from "pixi.js";
new Color([255, 0, 0]);
Correct:
import { Color } from "pixi.js";
new Color([1, 0, 0]);
new Color(0xff0000);
new Color("red");
new Color(new Uint8Array([255, 0, 0]));
Plain number arrays (number[] and Float32Array) use normalized 0-1 range. [255, 0, 0] clamps to [1, 0, 0] because values are clamped, but [200, 100, 50] does not produce the expected color. Use Uint8Array or Uint8ClampedArray for 0-255 input.
[MEDIUM] Using utils.string2hex or utils.hex2string
Wrong:
import { utils } from "pixi.js";
const hex = utils.string2hex("#ff0000");
Correct:
import { Color } from "pixi.js";
const hex = new Color("#ff0000").toNumber();
const str = new Color(0xff0000).toHex();
The utils namespace was removed in v8. Use the Color class for all color conversions.
API Reference