npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fiddle-digital/jitzy-three

v0.0.1

Published

Three.js bridge for projecting world-space anchors into @fiddle-digital/jitzy targets.

Readme

Jitzy Three

Jitzy Three is the Three.js bridge for Jitzy. Pin markers to meshes and world-space points, connect them with animated lines, and let those lines live inside your 3D scene — depth-tested, occluded by geometry, and always in the right perspective.

Built by Fiddle.Digital.

npm install @fiddle-digital/jitzy-three

Overview

What is Jitzy Three?

Jitzy Three connects the two worlds: a Three.js scene on one side, the Jitzy overlay on the other. It projects 3D anchors onto the screen every frame, keeps Jitzy targets in sync with them, and renders connectors as real scene objects when both ends have a position in 3D space. Mix in plain HTML elements — cards, labels, panels — and connect them to 3D objects just as easily.

Key Features

  • 3D Anchors: Attach a node to an Object3D, a fixed world position, or a function that returns one.
  • HTML Nodes: Register a real DOM element as a node, and optionally give it a depth so connectors touching it render in 3D.
  • Native 3D Connectors: Lines are real tube meshes in your scene, with true thickness, perspective, and depth testing.
  • Occlusion Culling: Markers and connectors hide when they move behind opaque geometry.
  • Offscreen Handling: Anchors outside the camera frustum are hidden automatically.
  • Animated Reveals: Marker and connector transitions work in 3D too.
  • Same API as Jitzy: Connect with jitzy.connect(a, b) — the bridge only handles the 3D part.
  • Effortless Setup: One mountThree() call and one update() per frame.

Who is Jitzy Three for?

Jitzy Three is perfect for:

  • Beginner Developers: Annotate a 3D model without learning projection math.
  • Experienced Developers: Use the low-level sync API when you need a custom camera or projection.
  • Designers: Combine HTML interface elements with 3D scenes, and tie them together visually.

Introduction

Why Jitzy Three?

Overlaying lines on a WebGL scene is deceptively hard. You have to project points every frame, hide them behind objects, handle off-screen anchors, and keep DOM elements and 3D positions in agreement. Jitzy Three takes care of all of it, so your scene stays focused on what it shows.

Benefits of Using Jitzy Three

  1. Simplicity: Add nodes, connect them, call update() — no manual projection.
  2. Depth-Aware Visuals: Connectors sit in the scene, so geometry correctly occludes them.
  3. Unified Workflow: 3D objects and HTML elements are both just nodes.
  4. Type Safety: Written in TypeScript, with every option typed.

Core Principles

  • Jitzy stays in charge: Jitzy owns targets, connectors, and styles; the bridge supplies positions and a 3D renderer.
  • Explicit connections: In 3D scenes you choose what connects to what.
  • Opt-in depth: HTML nodes stay on the flat overlay until you give them a depth.

Getting Started

Installation

npm install @fiddle-digital/jitzy @fiddle-digital/jitzy-three three

@fiddle-digital/jitzy (>=0.0.1 <0.1.0) and three (>=0.150) are peer dependencies.

Quick Start

The overlay is a container positioned exactly over your Three.js canvas, with the same size.

<div style="position: relative">
  <canvas id="scene"></canvas>
  <div id="overlay" style="position: absolute; inset: 0; pointer-events: none"></div>
</div>
import * as THREE from "three";
import { Jitzy } from "@fiddle-digital/jitzy";
import { mountThree } from "@fiddle-digital/jitzy-three";

// ...your renderer, scene, camera, and two meshes: meshA and meshB
// (unit cubes here, so z = 0.55 sits just above the front face)

const jitzy = Jitzy.mount(document.getElementById("overlay")!);
const three = mountThree(jitzy, camera, scene);

three.addNode({ id: "a", object: meshA, offset: [0, 0, 0.55], color: "#4488ff" });
three.addNode({ id: "b", object: meshB, offset: [0, 0, 0.55], color: "#44ddaa" });

jitzy.connect("a", "b", {
  color: "rgba(255, 255, 255, 0.6)",
  width: 1.5,
  curvature: 0.3,
});

function animate() {
  requestAnimationFrame(animate);
  three.update(); // before render()
  renderer.render(scene, camera);
}
animate();

⚠ Note: Place a node on the surface of an opaque mesh, not inside it. With occlusion culling on (the default), a point at the center of a solid mesh is behind that mesh's own surface, so its marker is hidden. Use offset, a child Object3D on the surface, or set occlusionCulling: false.

⚠ Note: Call three.update() before renderer.render(). The bridge adds markers and connectors to your scene, so this frame's changes need to land before this frame is drawn — otherwise they show up one frame late.

When you're done:

three.dispose();
jitzy.dispose();

API

mountThree(jitzy, camera, scene, options?)

Mounts the bridge on an existing Jitzy instance and returns a ThreeHandle.

| Option | Default | Description | | ------------------ | ------- | ------------------------------------------------------------------------ | | hideOffscreen | true | Hide anchors that fall outside the camera frustum | | occlusionCulling | true | Hide markers and connectors once they are behind opaque scene geometry |

⚠ Note: mountThree() requires an already-mounted Jitzy instance and switches its topology to explicit, so connections are the ones you create with jitzy.connect().

ThreeHandle

| Method | Description | | --------------------- | ------------------------------------------------- | | three.addNode(config) | Register a node | | three.removeNode(id) | Remove a node | | three.update() | Project anchors and sync Jitzy — call every frame | | three.dispose() | Remove all nodes registered through this handle |

addNode(config)

Give each node an id and one position source:

| Option | Type | Description | | ------------- | ---------------------------- | -------------------------------------------------------------------- | | id | string \| number | Node identifier, used when connecting | | object | Object3D | Follow this object's world position | | offset | [x, y, z] | Local offset from object, e.g. to sit on its surface | | position | [x, y, z] | A fixed world position | | getPosition | () => {x, y, z} | Compute the world position yourself, each frame | | element | HTMLElement | Use a real DOM element instead of a 3D position | | depth | number | For element nodes: distance from the camera, in world units |

Appearance and behavior:

| Option | Default | Description | | -------------------------- | ------- | -------------------------------------------------------------------------- | | color | — | Draws a colored dot marker. Without color, the node is an invisible connection point | | visible | true | Set false for a connection point with no visible marker | | markers | one centered marker ("default") | Custom marker positions and ids | | styles | — | Full marker style override (takes precedence over color/visible) | | hideWhenOffscreen | true | Hide this node when it leaves the frustum | | markerAnimationConfig | — | Marker enter/exit animation | | connectorAnimationConfig | — | Connector enter/exit animation |


Examples

Connect a 3D object to an HTML card

Registering an element with a depth lets connectors that touch it render in 3D:

three.addNode({
  id: "card",
  element: document.getElementById("card")!,
  depth: 8, // world units from the camera
  markers: [{ id: "default", xPercent: 0, yPercent: 50 }],
  visible: false, // the card is the visual — no dot needed
});

three.addNode({ id: "planet", object: planetMesh, color: "#aa55ff" });

jitzy.connect("planet", "card", { color: "rgba(170, 85, 255, 0.5)", width: 1.5 });

Without a depth, an element node stays on the flat 2D overlay and its connectors are drawn on top of the scene.

Fixed points and computed positions

three.addNode({ id: "north-pole", position: [0, 2, 0], color: "#ffffff" });

three.addNode({
  id: "orbiter",
  getPosition: () => ({ x: Math.cos(t) * 3, y: 0, z: Math.sin(t) * 3 }),
  color: "#44ddaa",
});

Invisible connection points

three.addNode({ id: "far-side", object: anchor, visible: false });
jitzy.connect("surface", "far-side", { curvature: 0.4 });

Connecting nodes with custom markers

jitzy.connect("a", "b") links each node's marker with the id "default". If you define your own markers, address them explicitly:

jitzy.connect(
  { target: "a", marker: "out" },
  { target: "b", marker: "in" },
);

Low-Level API

If you need your own camera setup or projection, the sync layer is available on its own:

import { createThreeSync } from "@fiddle-digital/jitzy-three";

const sync = createThreeSync(jitzy, {
  container: overlayElement,
  camera, // or: projectToNDC: (x, y, z) => ({ x, y, z })
  scene,
});

sync.addAnchor({ id: "a", object3D: mesh, markers: [{ id: "default", xPercent: 50, yPercent: 50 }] });
sync.update();

createThreeSync() returns addAnchor, removeAnchor, update, and dispose. It only syncs screen positions — to render connectors inside the scene, use mountThree().


Part of the Jitzy Ecosystem

| Package | Purpose | | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | | @fiddle-digital/jitzy | The runtime engine | | @fiddle-digital/jitzy-plugin-sdk | Build your own plugins, themes, and animations | | @fiddle-digital/jitzy-three | The Three.js bridge (this package) |


License

© Fiddle.Digital. All rights reserved. This package is proprietary software.


Bring your scene's story to the surface with Jitzy Three.