Space Adventure
An interactive 3D space canvas with drag-to-rotate and multi-input zoom controls.
Features: Drag to rotate the solar system in 3D. Pinch, double tap, or use keyboard/wheel to zoom.
Tip.
Drag to rotate. Pinch or double tap to zoom.
In Desktop, use 'z' + '+/-' or 'wheel' to zoom.
In Desktop, use 'z' + '+/-' or 'wheel' to zoom.
Signal Snapshot
SCALE 1.00
ROTATION 0, 0
INPUT -
Code
3D Rotation with Pan
import { pan } from "cereb";import { rotate3d } from "cereb/operators";
// Pan gesture -> 3D rotationpan(box, { threshold: 5 }) .pipe( rotate3d({ sensitivityX: 0.5, sensitivityY: 0.5, }), ) .on((signal) => { const [drx, dry, drz] = signal.value.rotation; rotationManager.addDelta(drx, dry, drz); });Pinch Zoom with Delta
import { pinch } from "cereb";import { zoom as createZoom, extend } from "cereb/operators";
const PINCH_SENSITIVITY = 0.4;
// Pinch zoom - uses delta-based zoom operatorpinch(box, { threshold: 10 }) .pipe( extend((signal) => ({ ratio: 1 + (signal.value.ratio - 1) * PINCH_SENSITIVITY, })), createZoom(), ) .on((signal) => { // Accumulate delta and clamp const newScale = clamp( zoomManager.getScale() + signal.value.scale, MIN_SCALE, MAX_SCALE ); zoomManager.setScale(newScale); });Keyboard & Wheel Zoom
import { wheel, keydown, keyheld } from "cereb";import { when, spy } from "cereb/operators";
const zoomMode$ = keyheld(window, { code: "KeyZ" }) .pipe(extend((signal) => ({ opened: signal.value.held })));
// 'z' + '+/-' keyboard zoomkeydown(window, { code: ["Equal", "Minus"] }) .pipe( when(zoomMode$), spy((signal) => signal.value.originalEvent.preventDefault()), ) .on((signal) => { const currentScale = zoomManager.getScale(); const multiplier = signal.value.code === "Equal" ? 1.2 : 1 / 1.2; const targetScale = clamp(currentScale * multiplier, MIN_SCALE, MAX_SCALE); zoomManager.setScale(targetScale); });
// 'z' + wheel zoomwheel(box, { passive: false }) .pipe( when(zoomMode$), spy((signal) => signal.value.originalEvent.preventDefault()), ) .on((signal) => { const currentScale = zoomManager.getScale(); const multiplier = Math.exp(-signal.value.deltaY * 0.005); const targetScale = clamp(currentScale * multiplier, MIN_SCALE, MAX_SCALE); zoomManager.setScale(targetScale); });