Skip to content

3D

Plot3D has its own container, an orbit camera and a light. Drag to orbit, wheel to zoom.

Layers

LayerCall
SurfaceaddSurface({ values, cols, rows, extentX, extentZ, colormap, wireframe })
Point cloudaddPointCloud({ x, y, z, size, sizes, colorBy, labels })
LineaddLine3D({ x, y, z })
BarsaddBar3D({ x, z, y, width, colorBy })
CuboidsaddBoxes3D({ boxes: [{ x, y, z, w, h, d, color, label }] })
QuiveraddQuiver3D({ x, y, z, u, v, w, scale })
ContouraddContour3D({ values, cols, rows, levels })
IsosurfaceaddIsosurface({ values, dims, isoLevel }) — marching cubes
VolumeaddVolume({ 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.

MIT licensed. WebGL2 required.