Skip to main content

3D Waterfall / Point-Line Chart

The 3D Waterfall Chart renders spectral or time-series data as stacked line slices in a 3D world, giving a sense of depth and evolution over time. Each slice is a PointLineRenderableSeries3DšŸ“˜ whose points share the same Z value, spreading the series along the Z axis to form the waterfall stack.

tip

The JavaScript 3D Point-Line Chart Example can be found in the SciChart.JS Examples Suite on GitHub, or in the live demo at scichart.com/demo.

Above: The JavaScript 3D Waterfall / Point-Line Chart example from the SciChart.js Demo

Create a 3D Waterfall Chart​

The waterfall depth effect is achieved by assigning every point in a slice the same Z value while incrementing that value for each successive slice. The X axis represents frequency (or whatever dimension varies within a slice) and the Y axis represents magnitude.

// Demonstrates how to create a 3D Waterfall Chart using PointLineRenderableSeries3D.
// Each "slice" is a PointLineRenderableSeries3D whose zValues are all set to the same
// value, spreading slices along the Z axis to produce the waterfall depth effect.

const { wasmContext, sciChart3DSurface } = await SciChart3DSurface.create(divElementId, {
theme: new SciChartJsNavyTheme(),
worldDimensions: new Vector3(300, 100, 300),
cameraOptions: {
position: new Vector3(-142, 310, 393),
target: new Vector3(0, 50, 0),
},
});

sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, {
axisTitle: "Frequency (Hz)",
drawMinorGridLines: false,
});
sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, {
axisTitle: "Power (dB)",
drawMinorGridLines: false,
visibleRange: new NumberRange(-30, 10),
});
sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, {
axisTitle: "Time",
drawMinorGridLines: false,
});

const sliceCount = 20;
const spectraSize = 200;

for (let i = 0; i < sliceCount; i++) {
const { xValues, yValues, zValues } = generateSpectralSlice(i, spectraSize);

// Color each point by its Y (power) value using a heat gradient
const low = Math.min(...yValues);
const high = Math.max(...yValues);
const metadata = yValues.map((y) => ({
vertexColor: valueToColor(y, low, high),
pointScale: 1,
}));

sciChart3DSurface.renderableSeries.add(
new PointLineRenderableSeries3D(wasmContext, {
dataSeries: new XyzDataSeries3D(wasmContext, { xValues, yValues, zValues, metadata }),
strokeThickness: 2,
opacity: 0.7,
})
);
}

sciChart3DSurface.chartModifiers.add(
new MouseWheelZoomModifier3D(),
new OrbitModifier3D(),
new ResetCamera3DModifier()
);

In the code above:

  • SciChart3DSurface.create() creates a 3D chart surface. worldDimensions sets the physical size of the 3D world in X, Y, Z units; cameraOptions positions the viewpoint.
  • sciChart3DSurface.xAxis / yAxis / zAxis — 3D charts use single-axis assignment (not .add()) for each of the three axes.
  • zValues.push(sliceIndex * 6) — all points in one slice share the same Z, and successive slices are spaced 6 units apart along Z, stacking them into the waterfall.
  • PointLineRenderableSeries3D with an XyzDataSeries3D renders each slice as a colored line in 3D space.
  • metadata[i].vertexColor — per-point color in UInt ARGB format, mapped from the Y (power) value through a heat gradient via uintArgbColorLerp.
  • OrbitModifier3D / MouseWheelZoomModifier3D / ResetCamera3DModifier — 3D-specific modifiers for orbit rotation, zoom, and camera reset.

The 3D API vs the 2D API​

Concept2D3D
SurfaceSciChartSurfaceSciChart3DSurface
AxisNumericAxis added via .xAxes.add()NumericAxis3D assigned to .xAxis / .yAxis / .zAxis
Data seriesXyDataSeriesXyzDataSeries3D
Renderable seriesFastLineRenderableSeriesPointLineRenderableSeries3D
Zoom/panZoomPanModifier, MouseWheelZoomModifierOrbitModifier3D, MouseWheelZoomModifier3D
Per-point colorPaletteProvidermetadata[i].vertexColor (UInt ARGB)

Point Markers​

PointLineRenderableSeries3D supports optional 3D point markers at each data point. Choose from:

Marker typeClass
SphereSpherePointMarker3DšŸ“˜
CubeCubePointMarker3DšŸ“˜
PyramidPyramidPointMarker3DšŸ“˜
CylinderCylinderPointMarker3DšŸ“˜
Ellipse (flat, camera-facing)EllipsePointMarker3DšŸ“˜
PixelPixelPointMarker3DšŸ“˜

Pass a marker instance to the pointMarker constructor option:

new PointLineRenderableSeries3D(wasmContext, {
dataSeries: ...,
strokeThickness: 2,
pointMarker: new EllipsePointMarker3D(wasmContext, { size: 3 }),
})

Per-Point Coloring with Metadata​

Color each point individually by supplying a metadata array on XyzDataSeries3D. The vertexColor property controls the point color as a UInt ARGB value. Use parseColorToUIntArgb() and uintArgbColorLerp() to map values to a gradient:

const metadata = yValues.map((y) => ({
vertexColor: valueToColor(y, low, high), // UInt ARGB
pointScale: 1,
}));

new XyzDataSeries3D(wasmContext, { xValues, yValues, zValues, metadata })
tip

Colors must be in UInt ARGB format where 0xFFFF0000 is opaque red. Use parseColorToUIntArgbšŸ“˜ to convert from CSS hex strings, and uintArgbColorLerpšŸ“˜ to blend between two colors.

See Also​