Building UI
Hit testing & events
Pointer events test each shape's real distance field: rings are hollow, lines react only within their stroke and rounded corners stay rounded.
Updated pixi-silk 0.1.0
Live demo
Source src/demos/hit-test.demo.ts
import { SilkGraphics } from 'pixi-silk';
import { defineDemo } from './runtime';
// containsPoint() evaluates the real distance field: the ring is hollow, the line is only its stroke.
export default defineDemo({
size: [480, 220],
setup({ stage, tick }) {
const items = [
{ draw: (g: SilkGraphics, c: number) => g.circle(100, 110, 60).stroke({ width: 18, color: c }) },
{ draw: (g: SilkGraphics, c: number) => g.roundRect(200, 50, 120, 120, 36, 0.6).fill(c) },
{
draw: (g: SilkGraphics, c: number) =>
g.polyline([350, 170, 390, 60, 450, 150]).stroke({ width: 10, cap: 'round', color: c }),
},
].map((item) => {
const g = new SilkGraphics();
g.eventMode = 'static';
g.cursor = 'pointer';
stage.addChild(g);
return { ...item, g, hover: false };
});
for (const item of items) {
item.g.on('pointerover', () => (item.hover = true));
item.g.on('pointerout', () => (item.hover = false));
}
tick(() => {
for (const item of items) item.draw(item.g.clear(), item.hover ? 0x30d158 : 0x48484a);
});
},
});Set eventMode and add listeners, as with any Pixi display object:
const button = new SilkGraphics();
button.eventMode = 'static';
button.cursor = 'pointer';
button.on('pointertap', () => console.log('tap'));
button.roundRect(0, 0, 160, 48, 24).fill(0x0a84ff);
containsPoint() first checks the object’s bounds. Then it runs the shader’s distance functions on
the CPU for the primitives under the pointer, last drawn first. A point is inside when its distance
to the painted region is negative:
- A stroked circle is a ring, so its centre is not inside.
- A line or polyline counts only within its stroke width.
- A rounded rect excludes the corners outside its radius.
- A blurred paint counts only up to its geometric edge.
You can also call it yourself:
if (g.containsPoint(g.toLocal(pointerGlobal))) { /* hovered */ }
In large interactive scenes, split independent targets into separate SilkGraphics objects. Then
each one hit-tests only its own primitives.
API reference: SilkGraphics