Skip to content

blparker/vizzy

Repository files navigation

Vizzy

npm CI minzipped size types license

Interactive visualization for TypeScript, built for the browser.

Documentation · Examples · Hub

Status: pre-1.0 (0.1.x). The API is stabilizing but may still change between minor versions.

Vizzy: interactive visualization in TypeScript

Why Vizzy?

Vizzy is for interactive visuals you can drop into a page. It's for people writing technical content (blog posts, docs, tutorials, explorable essays) who've hit the wall where static charts aren't enough but a whole JavaScript framework feels like overkill just to make a diagram move. Function graphs, geometric diagrams, algorithm walkthroughs: anywhere a moving, touchable picture beats prose.

It runs in TypeScript, renders in the browser, and is interactive by default, so you can drop a draggable derivative into a blog post, visualize a sorting algorithm in your docs, embed a classroom demo in a textbook, or prototype a visual proof directly in the page.

Vizzy isn't a charting library, a research notebook, or a Python-to-video pipeline. It's for interactive pictures that live inside your prose: ones the reader can drag, slide, and explore.

If you've used manim, you'll recognize a few ideas. Vizzy is its own project, shaped around the browser, async/await, and live interaction rather than offline video rendering.

Quick start

npm install @vizzyjs/core @vizzyjs/renderer-canvas
import { circle, fadeIn, sky } from '@vizzyjs/core';
import { createScene } from '@vizzyjs/renderer-canvas';

const canvas = document.querySelector('canvas')!;
const { add, play, grid } = createScene(canvas);

grid();
const c = circle({ radius: 1, color: sky });
add(c);
await play(fadeIn(c));

▶ Open in Hub

Using React? See @vizzyjs/react for a useScene hook that handles the canvas ref and lifecycle for you.

Animate it

play() returns a Promise. await sequences animations without queues or schedulers.

import { circle, fadeIn, fadeOut, animateShift, animateRotate, animateColor, sky, violet } from '@vizzyjs/core';
import { createScene } from '@vizzyjs/renderer-canvas';

const canvas = document.querySelector('canvas')!;
const { add, play } = createScene(canvas);

const c = circle({ color: sky });
add(c);

await play(fadeIn(c));
await play(animateShift(c, [3, 0]));
await play(animateRotate(c, Math.PI * 2));
await play(animateColor(c, { stroke: violet }));
await play(fadeOut(c));

▶ Open in Hub

Make it interactive

Drag a point around and update its label in world coordinates.

import { circle, text, sky, white } from '@vizzyjs/core';
import { createScene } from '@vizzyjs/renderer-canvas';

const canvas = document.querySelector('canvas')!;
const { add, grid, interact } = createScene(canvas);

grid();

const dot = circle({ radius: 0.2, style: { fill: sky, stroke: null } });
const label = text({
    content: '(0.0, 0.0)',
    position: [0, 0.5],
    style: { fill: white, fontSize: 0.25 },
});
add(dot, label);

interact.draggable(dot, {
    onDrag(pos) {
        dot.moveTo(pos);
        label.position = [pos[0], pos[1] + 0.5];
        label.content = '(' + pos[0].toFixed(1) + ', ' + pos[1].toFixed(1) + ')';
    },
});

▶ Open in Hub

Packages

Package Description
@vizzyjs/core Render-agnostic core: shapes, scene graph, animations, math utilities
@vizzyjs/renderer-canvas Canvas2D renderer with controls and interaction
@vizzyjs/react React bindings: useScene hook

Highlights

  • Shapes, not draw calls. 30+ factories (circles, axes, function graphs, TeX, arrows, braces, angles) with defaults that don't make you fight them.
  • Animate with await. await play(fadeIn(c)) does the obvious thing. Sequence with await, parallelize with play(a, b, c). No animation scheduler to learn.
  • Interaction isn't an afterthought. Shapes can be dragged, hovered, and clicked. Sliders, checkboxes, and color pickers re-render the scene on change. No event wiring required.
  • Think in math, not pixels. 14×8 world units, Y-up, origin at center. radius: 1 is a unit circle, not a 100-pixel blob. DPR and canvas resize handled for you.
  • Function graphs that don't lie. Discontinuities are handled without phantom vertical lines. One-call helpers for tangents, secants, KaTeX labels, braces, and annotations.
  • Colors you won't have to google. The full Tailwind palette (22 scales × 11 shades) baked in. Reach for sky[400] instead of memorizing #0ea5e9.

Development

This is a pnpm workspace.

pnpm install
pnpm playground   # local dev sandbox with Monaco editor + live preview
pnpm test
pnpm typecheck

See CONTRIBUTING.md for how to actually ship a contribution: workflow, code conventions, and tips on adding new shapes or animations.

Roadmap

Vizzy is pre-1.0. The API is stabilizing but will still move between minor versions.

Landing next:

  • SVG renderer. The Renderer interface is already backend-agnostic; SVG is the next implementation, useful for print, export, and accessibility trees.
  • Richer interaction primitives. Constrained dragging, keyboard handlers, animated drag paths.
  • Community shape registry. A shadcn-style catalog where contributors publish shapes (diagrams, domain-specific helpers, custom visuals) and you copy them into your project instead of adding a dep. Keeps the core small; keeps ownership with you.
  • 1.0 API freeze. Once the surface settles, committing to a 1.0.
  • Scene export. Record a scene to GIF or MP4 from code, without the screen-capture dance.

Explicitly not on the roadmap (for 1.0):

  • 3D rendering. Out of scope; browser-native 3D is a different product.
  • A chart DSL. @vizzyjs/core is primitive-level by design.
  • Svelte / Vue bindings. Welcome as community packages once the core API freezes.

Ideas, bug reports, and use cases are welcome in Discussions and Issues.

License

MIT

About

Interactive math visualization for TypeScript. Shapes, animations, and live controls in the browser.

Topics

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors