Optional filters
Full-page experience · Open playground
Import a blur factory, animate its input, and keep the original click geometry.
Try it
Section titled “Try it”Toggle blur, change its radius, and click inside and just outside the orange outline.
What to learn
Section titled “What to learn”- Use an explicitly imported appearance-only filter.
- Observe unchanged target geometry while blur changes.
Integration boundaries
Section titled “Integration boundaries”- The filter changes pixels only. The orange outline stays aligned with the click target.
- Importing one filter does not require the other effects.
This is a Pibbl Canvas example. Its mount owns its runtime resources; call its controller’s dispose method when removing it. The preview starts automatically unless reduced motion is enabled; Stop disposes the mount. Preserve the source’s logical canvas size and aspect ratio. Native HTML is not captured by Canvas filters.
Related APIs
Section titled “Related APIs”Complete source
Section titled “Complete source”Host setup for this source: use a canvas with width 720 and height 420, compile with jsx: "react-jsx" and jsxImportSource: "@pibbl/core", import its default mount, and call const controller = mount(canvas) after attaching the canvas. Call controller.dispose() before removing it.
optional-filters.example.tsx
Section titled “optional-filters.example.tsx”import { pibbl, Group, Rectangle, Text, useSignal, type PibblController } from '@pibbl/core';import { blur } from '@pibbl/core/filters';
function OptionalFilters() { const enabled = useSignal(true); const radius = useSignal(4); const clicks = useSignal(0); return ( <Group> <Rectangle style={{ width: 720, height: 420, fill: '#f7f0df' }} /> <Text style={{ left: 40, top: 48, font: '800 27px sans-serif', fill: '#17211d' }}> Appearance changes. Targets stay put. </Text> <Text style={{ left: 40, top: 78, font: '14px sans-serif', fill: '#52615c' }}> Toggle blur, then click the teal square or its soft edge. </Text> <Group style={{ filter: enabled.get() ? blur({ radius }) : [] }}> <Rectangle style={{ left: 240, top: 122, width: 240, height: 160, fill: '#127e79', cursor: 'pointer' }} onClick={() => clicks.update(value => value + 1)} /> <Text pointerEvents="none" style={{ left: 360, top: 211, textAlign: 'center', font: '800 23px sans-serif', fill: '#ffffff' }}> CLICK ME </Text> </Group> <Rectangle pointerEvents="none" style={{ left: 240, top: 122, width: 240, height: 160, stroke: '#d1782b', strokeWidth: 2 }} /> <Rectangle style={{ left: 40, top: 330, width: 190, height: 48, fill: '#17211d', cursor: 'pointer' }} onClick={() => enabled.update(value => !value)} /> <Text pointerEvents="none" style={{ left: 135, top: 360, textAlign: 'center', font: '700 15px sans-serif', fill: '#ffffff' }}> {enabled.get() ? 'TURN BLUR OFF' : 'TURN BLUR ON'} </Text> <Rectangle style={{ left: 250, top: 330, width: 190, height: 48, fill: '#ffffff', stroke: '#17211d', strokeWidth: 1, cursor: 'pointer' }} onClick={() => radius.update(value => value === 4 ? 12 : 4)} /> <Text pointerEvents="none" style={{ left: 345, top: 360, textAlign: 'center', font: '700 15px sans-serif', fill: '#17211d' }}> {`BLUR RADIUS ${radius.get()}`} </Text> <Text pointerEvents="none" style={{ left: 475, top: 360, font: '700 16px monospace', fill: '#17211d' }}> {`CLICKS ${clicks.get()}`} </Text> <Text pointerEvents="none" style={{ left: 40, top: 403, font: '12px sans-serif', fill: '#52615c' }}> The orange outline marks the original target geometry. </Text> </Group> );}
export default function mount(canvas: HTMLCanvasElement): PibblController { return pibbl(canvas, <OptionalFilters />);}Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.