Interactive bitmap layer
Draw a dot into an OffscreenCanvas and route clicks through Pibbl’s event boundary.
APIs demonstrated
Section titled “APIs demonstrated”- defineRenderLayer from
@pibbl/core - PibblRenderLayerComponentProps from
@pibbl/core - PibblRenderLayerContext from
@pibbl/core - PibblRenderLayerDefinition from
@pibbl/core - PibblRenderLayerFrame from
@pibbl/core - PibblRenderLayerHit from
@pibbl/core - PibblRenderLayerInput from
@pibbl/core - PibblRenderLayerInteraction from
@pibbl/core - PibblRenderLayerInteractionSnapshot from
@pibbl/core - PibblRenderLayerProps from
@pibbl/core - PibblRenderLayerSize from
@pibbl/core - PibblRenderLayerStyle from
@pibbl/core - PibblRenderLayerTarget from
@pibbl/core
Complete example
Section titled “Complete example”Plain source. Run as a browser module after the document body exists. TSX uses jsx: "react-jsx" and jsxImportSource: "@pibbl/core".
import { pibbl, defineRenderLayer, type PibblRenderLayerComponentProps, type PibblRenderLayerContext, type PibblRenderLayerDefinition, type PibblRenderLayerFrame, type PibblRenderLayerHit, type PibblRenderLayerInput, type PibblRenderLayerInteraction, type PibblRenderLayerInteractionSnapshot, type PibblRenderLayerProps, type PibblRenderLayerSize, type PibblRenderLayerStyle, type PibblRenderLayerTarget } from '@pibbl/core';
interface DotProps { readonly x: number; readonly y: number }interface DotTarget { readonly id: 'dot' }interface DotResources { readonly context: OffscreenCanvasRenderingContext2D; readonly invalidate: () => void; readonly target: DotTarget; active: boolean; elapsed: number;}
const status = document.createElement('p');status.textContent = 'Click the dot';const canvas = document.createElement('canvas');canvas.width = 320;canvas.height = 200;document.body.append(canvas, status);
const interaction: PibblRenderLayerInteraction<DotProps, DotResources, DotTarget> = { settle(resources, props, size) { const target: PibblRenderLayerTarget<DotTarget> = { target: resources.target, cursor: 'pointer', handlers: { onClick: () => undefined }, }; const snapshot: PibblRenderLayerInteractionSnapshot<DotTarget> = { targets: [target], hitTest(point): PibblRenderLayerHit<DotTarget> { const dx = point.x - props.x; const dy = point.y - props.y; if (point.x < 0 || point.y < 0 || point.x > size.width || point.y > size.height) { return { kind: 'miss' }; } return dx * dx + dy * dy <= 24 * 24 ? { kind: 'target', target: resources.target } : { kind: 'miss' }; }, onInput(input: Readonly<PibblRenderLayerInput<DotTarget>>) { if (input.type !== 'click' || input.hit.kind !== 'target') return; resources.active = !resources.active; status.textContent = resources.active ? `Dot selected after ${resources.elapsed.toFixed(1)}s` : 'Click the dot'; resources.invalidate(); }, }; return snapshot; },};
const definition: PibblRenderLayerDefinition<DotProps, DotResources, DotTarget> = { create(context: Readonly<PibblRenderLayerContext>): DotResources { const drawing = context.canvas.getContext('2d'); if (!drawing) throw new Error('Offscreen Canvas 2D is unavailable.'); return { context: drawing, invalidate: context.invalidate, target: { id: 'dot' }, active: false, elapsed: 0 }; }, resize(resources, size: Readonly<PibblRenderLayerSize>) { resources.context.canvas.width = size.backingWidth; resources.context.canvas.height = size.backingHeight; }, render(resources, frame: Readonly<PibblRenderLayerFrame>, context) { resources.elapsed += frame.deltaSeconds; const { width, height, pixelRatioX, pixelRatioY } = context.size; const drawing = resources.context; drawing.setTransform(pixelRatioX, 0, 0, pixelRatioY, 0, 0); drawing.clearRect(0, 0, width, height); drawing.fillStyle = resources.active ? '#be123c' : '#0f766e'; drawing.beginPath(); drawing.arc(160, 100, 24, 0, Math.PI * 2); drawing.fill(); }, interaction,};
const DotLayer = defineRenderLayer(definition);const style: PibblRenderLayerStyle = { width: 320, height: 200 };const componentProps: PibblRenderLayerComponentProps = { style, missBehavior: 'pass-through' };const props: PibblRenderLayerProps<DotProps> = { ...componentProps, x: 160, y: 100 };const controller = pibbl(canvas, <DotLayer {...props} />);window.addEventListener('pagehide', () => controller.dispose(), { once: true });Usage notes
Section titled “Usage notes”- Requires browser OffscreenCanvas and transferToImageBitmap support.
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 380919b. ALPHA — NOT FOR PRODUCTION USE.