Claude
Skills
Sign in
Back

pixijs-math

Included with Lifetime
$97 forever

Use this skill when working with coordinates, vectors, matrices, shapes, hit testing, or layout rectangles in PixiJS v8. Covers Point/ObservablePoint, Matrix (2D affine, decompose, apply, applyInverse), shapes (Rectangle, Circle, Ellipse, Polygon, RoundedRectangle, Triangle), Rectangle layout helpers (pad, fit, enlarge, ceil, scale, getBounds), strokeContains hit tests, Polygon isClockwise/containsPolygon, toGlobal/toLocal, PointData/PointLike/Size types, DEG_TO_RAD, and pixi.js/math-extras vector and intersection helpers. Triggers on: Point, ObservablePoint, Matrix, Rectangle, Circle, Polygon, Triangle, RoundedRectangle, toGlobal, toLocal, hitArea, strokeContains, pad, fit, enlarge, ceil, getBounds, containsRect, intersects, isClockwise, math-extras, lineIntersection, segmentIntersection, DEG_TO_RAD, PointData.

AI Agents

What this skill does


PixiJS exposes lightweight math primitives (Point, Matrix, shape classes) used throughout the library for transforms, hit testing, and coordinate conversion. Import `pixi.js/math-extras` to add vector operations (add, dot, magnitude, reflect) and Rectangle intersection/union helpers.

## Quick Start

```ts
const parent = new Container();
parent.position.set(100, 100);
parent.scale.set(2);
app.stage.addChild(parent);

const child = new Container();
child.position.set(50, 50);
parent.addChild(child);

const globalPt = child.toGlobal(new Point(0, 0));

const m = new Matrix()
  .translate(100, 50)
  .rotate(Math.PI / 4)
  .scale(2, 2);
const world = m.apply(new Point(10, 20));

const hitArea = new Rectangle(0, 0, 200, 100);
console.log(hitArea.contains(50, 50));
```

**Related skills:** `pixijs-scene-container` (transform properties), `pixijs-events` (hitArea usage), `pixijs-scene-core-concepts` (culling with Rectangle).

## Core Patterns

### Point and ObservablePoint

Point is a simple {x, y} value type. ObservablePoint fires a callback when x or y changes; it is used internally by Container's position, scale, pivot, origin, and skew.

```ts
import { Point } from "pixi.js";

const p = new Point(10, 20);
p.set(30, 40); // set both
p.set(50); // x=50, y=50

const clone = p.clone();
console.log(p.equals(clone)); // true

p.copyFrom({ x: 1, y: 2 }); // accepts any PointData

// Point.shared: temporary point, reset to (0,0) on each access
const temp = Point.shared;
temp.set(100, 200);
// do not store a reference to Point.shared
```

Container properties like `position`, `scale`, `pivot`, `origin`, and `skew` are ObservablePoints. Setting `.x` or `.y` on them triggers transform recalculation automatically.

```ts
import { Container } from "pixi.js";

const obj = new Container();
obj.position.set(100, 200); // triggers observer -> marks transform dirty
obj.position.x = 150; // also triggers observer
```

### Matrix (2D affine transform)

Matrix represents a 3x3 affine transform: `| a c tx | b d ty | 0 0 1 |`. It supports translate, scale, rotate, append, prepend, invert, and decompose.

```ts
import { Matrix, Point } from "pixi.js";

// Build a transform
const m = new Matrix()
  .translate(100, 50)
  .rotate(Math.PI / 4)
  .scale(2, 2);

// Transform a point (local -> parent space)
const local = new Point(10, 20);
const world = m.apply(local);

// Inverse transform (parent -> local space)
const backToLocal = m.applyInverse(world);

// Combine matrices
const a = new Matrix().translate(50, 0);
const b = new Matrix().rotate(Math.PI / 2);
a.append(b); // a = a * b

// Decompose into position/scale/rotation/skew
const transform = {
  position: new Point(),
  scale: new Point(),
  pivot: new Point(),
  skew: new Point(),
  rotation: 0,
};
m.decompose(transform);
console.log(transform.rotation); // ~0.785 (PI/4)

// Shared temporary matrix (reset on each access)
const temp = Matrix.shared;
// IDENTITY is read-only reference
const isDefault = m.equals(Matrix.IDENTITY);
```

### Coordinate transforms via Container

Containers provide `toGlobal`, `toLocal`, and `getGlobalPosition` for coordinate conversion.

```ts
import { Container, Point } from "pixi.js";

const parent = new Container();
parent.position.set(100, 100);
parent.scale.set(2);

const child = new Container();
child.position.set(50, 50);
parent.addChild(child);

// Local point in child's space -> global (world) space
const globalPt = child.toGlobal(new Point(0, 0));
// globalPt = { x: 200, y: 200 } (100 + 50*2, 100 + 50*2)

// Global point -> child's local space
const localPt = child.toLocal(new Point(200, 200));
// localPt = { x: 0, y: 0 }

// Convert between two containers
const other = new Container();
other.position.set(300, 300);
const ptInOther = child.toLocal(new Point(10, 10), other);
```

### Shapes and hit testing

Rectangle, Circle, Ellipse, Polygon, RoundedRectangle, and Triangle all implement `contains(x, y)` for point-in-shape tests, plus `getBounds(out?)` and `strokeContains(x, y, width, alignment?)`. They can be used as `hitArea` on containers for custom interaction regions.

```ts
import { Rectangle, Circle, Polygon, Container } from "pixi.js";

const rect = new Rectangle(0, 0, 200, 100);
rect.contains(50, 50); // true
rect.contains(300, 50); // false
rect.left; // 0
rect.right; // 200
rect.top; // 0
rect.bottom; // 100
rect.isEmpty(); // false (Rectangle.EMPTY returns a fresh empty rect)

// Native Rectangle-to-Rectangle methods (no math-extras needed)
const other = new Rectangle(50, 50, 100, 100);
rect.containsRect(other); // true if `other` is fully inside `rect`
rect.intersects(other); // boolean: do they overlap at all?
rect.intersects(other, matrix); // overlap after transforming `other`

// Stroke hit testing (alignment: 1 = inner, 0.5 = centered, 0 = outer)
rect.strokeContains(0, 50, 4); // true if (0,50) lies on a 4px centered stroke
const circle = new Circle(100, 100, 50);
circle.strokeContains(150, 100, 4, 1); // inner-aligned stroke check

// getBounds works on every shape (returns a Rectangle, accepts an out param)
const bounds = circle.getBounds();
const reused = new Rectangle();
new Polygon([0, 0, 100, 0, 50, 100]).getBounds(reused);

// Use as hit area for interaction
const button = new Container();
button.hitArea = new Rectangle(0, 0, 200, 50);
button.eventMode = "static";
button.on("pointerdown", () => {
  /* clicked */
});
```

Do not confuse native `Rectangle.intersects(other)` (returns `boolean`) with math-extras `intersection(other)` (returns a `Rectangle` describing the overlap area).

### Rectangle layout helpers

Rectangle ships with mutating helpers used heavily in UI/layout, bounds aggregation, and pixel snapping. All return `this` for chaining.

```ts
import { Rectangle } from "pixi.js";

const r = new Rectangle(10, 10, 100, 50);

r.pad(5); // grow on all sides: x=5, y=5, w=110, h=60
r.pad(10, 4); // separate horizontal/vertical padding
r.scale(2); // multiply x, y, width, height by 2

// fit shrinks `this` to lie inside another rect (clipping)
const viewport = new Rectangle(0, 0, 200, 200);
new Rectangle(150, 150, 200, 200).fit(viewport); // -> 150, 150, 50, 50

// enlarge expands `this` to include another rect (bounds aggregation)
const total = new Rectangle();
items.forEach((item) =>
  total.enlarge(new Rectangle().copyFromBounds(item.getBounds())),
);

// ceil snaps to a pixel grid (resolution: 1 = whole pixels, 2 = half pixels)
new Rectangle(10.2, 10.6, 100.8, 100.4).ceil();

// copy a Container/Mesh bounds object straight into a Rectangle
new Rectangle().copyFromBounds(container.getBounds());
```

### Polygon

Polygon accepts four constructor formats: a flat number array, an array of point-like objects, or either passed as spread arguments.

```ts
import { Polygon, Point } from "pixi.js";

new Polygon([0, 0, 100, 0, 50, 100]); // flat numbers
new Polygon([new Point(0, 0), new Point(100, 0), new Point(50, 100)]); // PointData[]
new Polygon(0, 0, 100, 0, 50, 100); // spread numbers
new Polygon(new Point(0, 0), new Point(100, 0), new Point(50, 100)); // spread points

const poly = new Polygon([0, 0, 100, 0, 100, 100, 0, 100]);
poly.points; // [0, 0, 100, 0, 100, 100, 0, 100] (mutable flat array)
poly.closePath; // true by default; false produces an open path
poly.startX; // 0  - first vertex
poly.lastX; // 0  - last vertex (lastY for y)
poly.isClockwise(); // shoelace winding test (useful for SVG hole detection)

// Polygon-in-polygon containment for hole detection
const outer = new Polygon([0, 0, 100, 0, 100, 100, 0, 100]);
const hole = new Polygon([25, 25, 75, 25, 75, 75, 25, 75]);
outer.containsPolygon(hole); // true
```

### Constants

```ts
import { DEG_TO_RAD, RAD_TO_DEG, PI_2 } from "pixi.js";

const angle = 45 * DEG_TO_RAD; // 0.785...
const degrees = angle * RAD_TO_DEG; // 45
const fullCircle = PI_2; // Math.PI * 2
```

### Types

- `PointData` - minimal `{x, y}` interface accepted by most APIs. Use it when typing parameters that only need to read 
Files: 1
Size: 15.0 KB
Complexity: 30/100
Category: AI Agents

Related in AI Agents