# 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.

Source: https://pixi-silk.schmooky.dev/docs/hit-testing/

Live demo `hit-test` (source):

```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:

```ts
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:

```ts
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.
