3D
Plot3D has its own container, an orbit camera and a light. Drag to orbit, wheel to zoom.
Layers
| Layer | Call |
|---|---|
| Surface | addSurface({ values, cols, rows, extentX, extentZ, colormap, wireframe }) |
| Point cloud | addPointCloud({ x, y, z, size, sizes, colorBy, labels }) |
| Line | addLine3D({ x, y, z }) |
| Bars | addBar3D({ x, z, y, width, colorBy }) |
| Cuboids | addBoxes3D({ boxes: [{ x, y, z, w, h, d, color, label }] }) |
| Quiver | addQuiver3D({ x, y, z, u, v, w, scale }) |
| Contour | addContour3D({ values, cols, rows, levels }) |
| Isosurface | addIsosurface({ values, dims, isoLevel }) — marching cubes |
| Volume | addVolume({ values, dims, colormap, density }) — GPU raymarch |
Volumes are indexed x + y*nx + z*nx*ny.
Framing
The default fit stretches each axis to fill the view cube, which is right for a surface but wrong for anything long and thin. Two options control it:
ts
new Plot3D(el, {
aspectMode: "data", // one shared scale — true proportions
projection: "orthographic", // no perspective divide, constant scale end to end
showAxes: false, // hide the box, ticks and labels
});Under orthographic, distance sets the visible half-height rather than the eye distance, so the wheel still zooms.
Labels in 3D
Pin text to a point in data space; it is re-projected every frame, so it tracks the camera, and it is outlined so it stays readable over any fill.
ts
plot.addLabel3D({ x, y, z, text: "peak", dy: -10, baseline: "bottom" });
plot.clearLabels3D();Chrome
title, legend, colorbar, gridPlanes, autoRotate, lightControls, resetButton and downloadButton are all options; setLight({ azimuth, elevation, ambient }) and resetView() are methods.