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):
| Callback | Fires 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))
}