Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CanvasKit: Interactive Canvases

When a sketch needs hit-testing, pointer / keyboard events, pan, or zoom, pair it with CanvasKit. Register hit regions by ID inside draw, install callbacks once on the kit itself, and wire pan/zoom automatically.

Hit regions

#![allow(unused)]
fn main() {
use blinc_canvas_kit::prelude::*;

struct Scene {
    kit: CanvasKit,
    hovered: Option<String>,
}

impl Sketch for Scene {
    fn setup(&mut self, _ctx: &mut SketchContext<'_>) {
        self.kit.on_element_click(|ev| {
            println!("clicked region: {}", ev.id);
        });

        // Note: hover callbacks run on pointer enter / leave. Persist the
        // hovered id into sketch state to drive per-frame highlight logic.
        let hovered = /* reference-counted handle back into sketch state */;
        self.kit.on_element_hover(move |ev| {
            // update `hovered` here
        });
    }

    fn draw(&mut self, ctx: &mut SketchContext<'_>, _t: f32, _dt: f32) {
        // Register hit regions each frame (IDs flow into the callbacks).
        self.kit.hit_rect("box-a", Rect::new(50.0, 50.0, 100.0, 100.0));
        self.kit.hit_rect("box-b", Rect::new(200.0, 50.0, 100.0, 100.0));

        // Draw — pick color based on whatever the hover callback stashed.
    }
}
}

Callbacks

All installed on the CanvasKit once (typically in setup or at construction):

CallbackFires on
on_element_click(cb)Click on a hit region
on_element_hover(cb)Enter / leave a hit region
on_element_drag(cb)Drag a hit region
on_element_drag_end(cb)Drag release
on_selection_change(cb)Multi-select / marquee changes

Each callback receives a CanvasEvent carrying the region id, the content-space pointer position, and the triggering EventContext.

Built-in gestures

CanvasKit wires the following automatically once it’s in a sketch:

  • Pan — drag on empty background
  • Zoom — scroll wheel (content-space)
  • Marquee select — drag from empty background with shift / modifier
  • Grid snap — configurable via kit.snap_rect(rect) / kit.snap_point(p)

Tune sensitivity via the builder methods before mounting:

#![allow(unused)]
fn main() {
let kit = CanvasKit::new("scene")
    .with_drag_sensitivity(1.0)
    .with_zoom_sensitivity(0.1)
    .with_momentum_decay(0.92);
}

Content-space vs screen-space

hit_rect and hit_test operate on content-space coordinates (pre-pan, pre-zoom). The kit transforms pointer events and render bounds into content space before dispatching — you author as if the canvas were infinite and at 1:1 zoom. Use kit.is_visible(rect) to cull content-space rects against the current viewport before drawing expensive primitives.

Full example

See the Canvas Kit Interactive example for a complete walkthrough with pan, zoom, hover feedback, drag, marquee select, and a HUD overlay.

Bundled input routing

To pipe every event the kit receives (pointer, scroll, key) into a single callback — useful for bridging into blinc_input::InputState::record or custom routing — attach .on_canvas_events(|e| ...) to the Div returned by sketch():

#![allow(unused)]
fn main() {
use blinc_canvas_kit::sketch::SketchEvents;

sketch("scene", Scene { kit: CanvasKit::new("scene") })
    .on_canvas_events(|ev| input.record(ev))
}