Angular Column 3D Chart

The SciChart.js Angular 3D Column Chart uses uses XYZ data and can show sparse or grid based columns, with indivdual column coloring and a variety of column shapes.

Data-point width 1

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.tsx

theme.ts

Copy to clipboard
Minimise
Fullscreen
1import {
2    SciChart3DSurface,
3    CameraController,
4    Vector3,
5    EWatermarkPosition,
6    MouseWheelZoomModifier3D,
7    OrbitModifier3D,
8    NumericAxis3D,
9    HeatmapLegend,
10    TSciChart3D,
11    XyzDataSeries3D,
12    parseColorToTArgb,
13    CubePointMarker3D,
14    PyramidPointMarker3D,
15    SpherePointMarker3D,
16    CylinderPointMarker3D,
17    ColumnRenderableSeries3D,
18    toHex,
19    TArgb,
20    parseColorToUIntArgb,
21    TSciChart,
22} from "scichart";
23import { appTheme } from "../../../theme";
24
25export enum EColumn3DType {
26    CylinderPointMarker3D = "Cylinder",
27    CubePointMarker3D = "Cube",
28    PyramidPointMarker3D = "Pyramid",
29    SpherePointMarker3D = "Sphere",
30}
31
32export enum EColumnColorMode {
33    X = "X",
34    XZ = "XZ",
35    Height = "Height",
36    Series = "Series",
37}
38
39export async function drawExample(divElementId: string | HTMLDivElement) {
40    const { sciChart3DSurface, wasmContext } = await SciChart3DSurface.create(divElementId, {
41        theme: appTheme.SciChartJsTheme,
42    });
43
44    sciChart3DSurface.camera = new CameraController(wasmContext, {
45        position: new Vector3(-300, 300, -300),
46        target: new Vector3(0, 50, 0),
47    });
48    sciChart3DSurface.watermarkPosition = EWatermarkPosition.TopLeft;
49    sciChart3DSurface.chartModifiers.add(new MouseWheelZoomModifier3D());
50    sciChart3DSurface.chartModifiers.add(new OrbitModifier3D());
51    // sciChart3DSurface.chartModifiers.add(new TooltipModifier3D({ showTooltip: true, crosshairStroke: 'green', crosshairStrokeThickness: 2 }));
52
53    sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, { axisTitle: "X Axis" });
54    sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, { axisTitle: "Y Axis" });
55    sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, { axisTitle: "Z Axis" });
56
57    const dataSeries = new XyzDataSeries3D(wasmContext);
58    // size in the point marker is ignored, use dataPointWidthX and dataPointWidthZ instead!
59    const series = new ColumnRenderableSeries3D(wasmContext, {
60        dataSeries,
61        pointMarker: createPointMarker3D(wasmContext, EColumn3DType.CylinderPointMarker3D, appTheme.VividOrange),
62        dataPointWidthX: 0.9,
63        dataPointWidthZ: 0.9,
64        useMetadataColors: true,
65    });
66
67    const updateData = (colorMode: EColumnColorMode, update: boolean) => {
68        const startX = 0;
69        const stepX = 1;
70        const countX = 10;
71        const startZ = 0;
72        const stepZ = 1;
73        const countZ = 30;
74        const minY = 0;
75        const maxY = 40;
76        const startColor = parseColorToTArgb(appTheme.VividTeal);
77        const endColor = parseColorToTArgb(appTheme.VividPink);
78
79        let i = 0;
80        for (let xIndex = 0; xIndex < countX; xIndex++) {
81            const x = startX + xIndex * stepX;
82            for (let zIndex = 0; zIndex < countZ; zIndex++) {
83                const z = startZ + zIndex * stepZ;
84                let y: number;
85                if (update) {
86                    y = dataSeries.getNativeYValues().get(i);
87                } else {
88                    y = Math.random() * maxY * (x / (2 * countX) + 0.5);
89                }
90
91                let vertexColor: number;
92                let c: number;
93                let cmax: number;
94                if (colorMode === EColumnColorMode.Height) {
95                    vertexColor = colorInterpolation(startColor, endColor, minY, maxY, y);
96                } else if (colorMode === EColumnColorMode.X) {
97                    c = x;
98                    cmax = countX;
99                    vertexColor = parseColorToUIntArgb(
100                        appTheme.SciChartJsTheme.getStrokeColor(c, cmax, wasmContext as unknown as TSciChart)
101                    );
102                } else if (colorMode === EColumnColorMode.XZ) {
103                    c = x * z;
104                    cmax = countX * countZ;
105                    vertexColor = parseColorToUIntArgb(
106                        appTheme.SciChartJsTheme.getStrokeColor(c, cmax, wasmContext as unknown as TSciChart)
107                    );
108                }
109                series.useMetadataColors = colorMode !== EColumnColorMode.Series;
110
111                if (update) {
112                    dataSeries.update(i, x, y, z, { vertexColor, pointScale: 1 });
113                } else {
114                    dataSeries.append(x, y, z, { vertexColor, pointScale: 1 });
115                }
116                i += 1;
117            }
118        }
119    };
120    sciChart3DSurface.renderableSeries.add(series);
121    updateData(EColumnColorMode.X, false);
122
123    const updateColors = (colorMode: EColumnColorMode) => {
124        updateData(colorMode, true);
125    };
126
127    const updatePointMarker = (type: EColumn3DType) => {
128        series.pointMarker = createPointMarker3D(wasmContext, type, appTheme.VividOrange);
129    };
130
131    return { sciChartSurface: sciChart3DSurface, controls: { updateColors, updatePointMarker } };
132}
133
134export function createPointMarker3D(wasmContext: TSciChart3D, type: EColumn3DType, fill: string) {
135    switch (type) {
136        case EColumn3DType.CubePointMarker3D:
137            return new CubePointMarker3D(wasmContext, { fill });
138        case EColumn3DType.PyramidPointMarker3D:
139            return new PyramidPointMarker3D(wasmContext, { fill });
140        case EColumn3DType.SpherePointMarker3D:
141            return new SpherePointMarker3D(wasmContext, { fill });
142        default:
143            return new CylinderPointMarker3D(wasmContext, { fill });
144    }
145}
146
147export function colorInterpolation(startColor: TArgb, endColor: TArgb, startY: number, endY: number, currentY: number) {
148    const redValue = Math.floor(lerpFn(startY, endY, startColor.red, endColor.red, currentY));
149    const greenValue = Math.floor(lerpFn(startY, endY, startColor.green, endColor.green, currentY));
150    const blueValue = Math.floor(lerpFn(startY, endY, startColor.blue, endColor.blue, currentY));
151
152    const hexStr = "0x" + toHex(255) + toHex(redValue) + toHex(greenValue) + toHex(blueValue);
153    return parseInt(hexStr, 16);
154}
155
156function lerpFn(minY: number, maxY: number, minColor: number, maxColor: number, v: number) {
157    return minColor + ((v - minY) * (maxColor - minColor)) / (maxY - minY);
158}
159

Angular Column 3D Chart

Overview

This example demonstrates an interactive 3D Column Chart built with SciChart.js and integrated within an Angular application. The chart renders a grid of 3D columns using XYZ data, allowing for dynamic updates in column shape and color modes. Developers can refer to the Getting Started with SciChart JS guide for an overview of setting up SciChart in Angular projects.

Technical Implementation

The implementation initializes the 3D chart asynchronously using SciChart.js, creating a SciChart3DSurface with numeric axes and attaching interactive modifiers such as Mouse Wheel Zoom and Orbit as described in the MouseWheelZoomModifier Documentation. The chart is configured using asynchronous functions to ensure that the WebGL context and chart surface are fully loaded before any updating of the data series occurs. For guidance on asynchronous chart initialization and setup, developers can consult the Tutorial 01 - Setting up a npm Project with SciChart.js.

Features and Capabilities

The example offers real-time update capabilities where dynamic changes such as modifying the column marker type and adjusting the data point width are applied instantly to the chart. The code employs dynamic color interpolation to change column colors based on data values, a process aligned with the documented techniques in the Append, Insert, Update, Remove | JavaScript Chart Documentation. Additionally, it uses TypeScript enums to seamlessly configure various options for column shapes (Cylinder, Cube, Pyramid, Sphere) and color modes, enhancing code readability and maintainability.

Integration and Best Practices

Although the example sources include components that appear in React, the Angular integration focuses on leveraging SciChart.js within an Angular project by using asynchronous initialization and Angular Material controls for user interaction. The integration uses Angular Material form controls to adjust chart settings such as column shape and color mode, following best practices outlined in resources like Integrating Angular ChartJs and Angular Material. Performance optimizations are inherent in the design, ensuring that updates do not hinder the interactivity of the 3D chart. Developers are encouraged to explore additional performance optimization techniques in the SciChart.js ecosystem to further enhance real-time interactivity.

SciChart Ltd, 16 Beaufort Court, Admirals Way, Docklands, London, E14 9XL.