The Graphics Development Kit for building interactive, animated, and reactive data visualizations in the browser.
VisQuill is built around a reactive model: visual elements are bound to data values and update automatically when those values change. Instead of manually synchronizing data and DOM, you declare what depends on what — VisQuill handles the rest.
Live examples: visquill.com/developers/lab
VisQuill GDK is published under a non-commercial license. It is free to use for personal, educational, research, and open-source projects. A commercial license is required for any use that directly or indirectly contributes to generating revenue.
See LICENSE for the full terms. For commercial licensing inquiries contact contact@visquill.com.
Alpha release — install with the
@alphatag. The API may change between versions.
npm install @visquill/visquill-gdk@alpha
import { VisQuill, Attach } from "@visquill/visquill-gdk"
const container = document.getElementById("viz") as HTMLDivElement
const rvg = VisQuill.create(container, "my-viz-")
const canvas = rvg.canvas
// Create a draggable handle and a label that follows it
const handle = canvas.handles.disk("handle", { x: 200, y: 200 })
const label = canvas.text.label("drag me", "label")
Attach.pointToPoint(label, handle, { offset: [0, -20] })
CSS classes are assembled automatically from the prefix chain:
graphic prefix + layer prefix + class name you pass in
"my-viz-" "" "handle"
──────────────────────►
→ "my-viz-handle"
Your stylesheet only needs the fully-qualified class name.
const rvg = VisQuill.create(div, "prefix-")
Creates an SVG element inside div and returns a reactive graphics context (Rvg). The prefix is prepended to every CSS class name generated within this graphic.
const canvas = rvg.canvas
const layer = canvas.layer("chart-")
Layers are nested groups with their own class prefix. The full class on an element is built by concatenating all prefixes in the chain.
Reactive.do([handle], () => {
label.value = `x = ${Math.round(handle.x)}`
})
Reactive.do registers a callback that fires whenever any listed dependency changes. Dependencies can be handles, shapes, or any reactive value.
Animate.eased(value, targetValue, 600, { easing: Animate.easeOutCubic })
Animate.sequence(value, [
{ to: 100, duration: 400 },
{ to: 0, duration: 400 }
], { loop: true })
Starting a new animation on the same reference automatically cancels the previous one.
Attach methods create persistent reactive bindings without requiring a Reactive.do block:
Attach.pointToPoint(label, handle, { offset: [0, -20] })
Attach.pointToSegment(dot, segment, { position: 0.5 })
Attach.rectangleToSegment(rect, 20, segment)
rvg.dispose()
// or
VisQuill.disposeAll()
Call this before unmounting or navigating away to release all graphics and event listeners.