JavaScript 3D Styling Demo Chart

This demonstrates the JavaScript 3D Styling capabilities of SciChart.js v5, including axis label positioning, and control over 3d plane visibility

Select Axis

Axis Font Size: 20

Axis Title Offset: 10

Tick Labels Offset: 10

Label Orientation Mode

Colors (Bands, Major, Minor)

Select Plane

Visability Mode

Draw Titles Mode

Draw Lables Mode

Is Visible

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.html

vanilla.ts

theme.ts

Copy to clipboard
Minimise
Fullscreen
1import {
2    CubePointMarker3D,
3    CylinderPointMarker3D,
4    EAxisPlaneDrawLabelsMode,
5    EAxisPlaneVisibilityMode,
6    EllipsePointMarker3D,
7    EThemeProviderType,
8    MouseWheelZoomModifier3D,
9    NumberRange,
10    NumericAxis3D,
11    OrbitModifier3D,
12    PixelPointMarker3D,
13    PyramidPointMarker3D,
14    QuadPointMarker,
15    ResetCamera3DModifier,
16    ScatterRenderableSeries3D,
17    SciChart3DSurface,
18    SciChartJSDarkTheme,
19    SciChartJSDarkv2Theme,
20    SciChartJSLightTheme,
21    SciChartJsNavyTheme,
22    SpherePointMarker3D,
23    TrianglePointMarker3D,
24    Vector3,
25    XyzDataSeries3D,
26} from "scichart";
27
28import { appTheme } from "../../../theme";
29import { E3DLabelOrientationMode } from "scichart/types/TextStyle3D";
30
31export type TAxis = "x" | "y" | "z";
32export type TSelectedAxisPlane = "xy" | "zy" | "zx" | "none";
33
34export const drawExample = async (rootElement: string | HTMLDivElement) => {
35    const { sciChart3DSurface, wasmContext } = await SciChart3DSurface.create(rootElement, {
36        theme: appTheme.SciChartJsTheme,
37        worldDimensions: new Vector3(300, 200, 300),
38    });
39    sciChart3DSurface.camera.position = new Vector3(-190.48, 272.08, -429.63);
40    sciChart3DSurface.camera.target = new Vector3(0, 60, 0);
41
42    sciChart3DSurface.chartModifiers.add(
43        new MouseWheelZoomModifier3D(),
44        new OrbitModifier3D(),
45        new ResetCamera3DModifier()
46    );
47
48    sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, {
49        axisTitle: "X Axis",
50        visibleRange: new NumberRange(25, 110),
51        labelPrecision: 0,
52        drawMajorGridLines: false,
53        drawMinorGridLines: false,
54        axisBandsFill: appTheme.DarkIndigo + "44",
55        tickLabelsOffset: 10,
56        majorGridLineStyle: { color: "#5588AA" },
57        minorGridLineStyle: { color: "#225588" },
58        labelOrientationMode: E3DLabelOrientationMode.Auto,
59    });
60    sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, {
61        axisTitle: "Y Axis",
62        visibleRange: new NumberRange(0, 50000),
63        labelPrecision: 0,
64        drawMajorGridLines: false,
65        drawMinorGridLines: false,
66        axisBandsFill: appTheme.DarkIndigo + "44",
67        tickLabelsOffset: 10,
68        majorGridLineStyle: { color: "#5588AA" },
69        minorGridLineStyle: { color: "#225588" },
70    });
71    sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, {
72        axisTitle: "Z Axis",
73        visibleRange: new NumberRange(1965, 2010),
74        labelPrecision: 0,
75        drawMajorGridLines: false,
76        drawMinorGridLines: false,
77        axisBandsFill: appTheme.DarkIndigo + "44",
78        tickLabelsOffset: 10,
79        majorGridLineStyle: { color: "#5588AA" },
80        minorGridLineStyle: { color: "#225588" },
81    });
82
83    // Utils to get/set axis settings
84    const getPlane = (plane: TSelectedAxisPlane) => {
85        switch (plane) {
86            case "xy":
87                return sciChart3DSurface.xyAxisPlane;
88            case "zy":
89                return sciChart3DSurface.zyAxisPlane;
90            case "zx":
91                return sciChart3DSurface.zxAxisPlane;
92            default:
93                return null;
94        }
95    };
96
97    const setPlaneBackground = (plane: TSelectedAxisPlane) => {
98        sciChart3DSurface.xAxis.axisPlaneBackgroundFill = "transparent";
99        sciChart3DSurface.yAxis.axisPlaneBackgroundFill = "transparent";
100        sciChart3DSurface.zAxis.axisPlaneBackgroundFill = "transparent";
101        const unselectedPlaneColor = "#44444466";
102        if (plane === "xy") {
103            sciChart3DSurface.zAxis.axisPlaneBackgroundFill = unselectedPlaneColor;
104        } else if (plane === "zy") {
105            sciChart3DSurface.xAxis.axisPlaneBackgroundFill = unselectedPlaneColor;
106        } else if (plane === "zx") {
107            sciChart3DSurface.yAxis.axisPlaneBackgroundFill = unselectedPlaneColor;
108        }
109    };
110    setPlaneBackground("none"); // init - does nothing with "none" but it's kept for clarity
111
112    const setIsPlaneVisible = (plane: TSelectedAxisPlane, mode: string) => {
113        getPlane(plane).isVisible = mode === "true";
114    };
115
116    const setDrawLabelsMode = (plane: TSelectedAxisPlane, mode: EAxisPlaneDrawLabelsMode) => {
117        getPlane(plane).drawLabelsMode = mode;
118    };
119
120    const setDrawTitlesMode = (plane: TSelectedAxisPlane, mode: EAxisPlaneDrawLabelsMode) => {
121        getPlane(plane).drawTitlesMode = mode;
122    };
123
124    const setVisibilityMode = (plane: TSelectedAxisPlane, mode: string) => {
125        if (mode === "auto") {
126            getPlane(plane).visibilityMode = EAxisPlaneVisibilityMode.Auto;
127        }
128        if (mode === "negativeSide") {
129            getPlane(plane).visibilityMode = EAxisPlaneVisibilityMode.NegativeSide;
130        }
131        if (mode === "positiveSide") {
132            getPlane(plane).visibilityMode = EAxisPlaneVisibilityMode.PositiveSide;
133        }
134    };
135
136    const getAxis = (axis: TAxis) => {
137        if (axis === "x") return sciChart3DSurface.xAxis;
138        if (axis === "y") return sciChart3DSurface.yAxis;
139        return sciChart3DSurface.zAxis;
140    };
141
142    const setTitleOffset = (offset: number, axis: TAxis) => {
143        getAxis(axis).titleOffset = offset;
144    };
145
146    const setTickLabelsOffset = (offset: number, axis: TAxis) => {
147        getAxis(axis).tickLabelsOffset = offset;
148    };
149
150    const setAxisLabelFontSize = (value: number, axis: TAxis) => {
151        getAxis(axis).labelStyle.fontSize = value;
152    };
153
154    // Create different point markers for each data point
155    const pointMarkers = [
156        new EllipsePointMarker3D(wasmContext, { size: 10 }),
157        new TrianglePointMarker3D(wasmContext, { size: 10 }),
158        new PixelPointMarker3D(wasmContext, { size: 10 }),
159        new QuadPointMarker(wasmContext, { size: 10 }),
160        new SpherePointMarker3D(wasmContext, { size: 10 }),
161        new CubePointMarker3D(wasmContext, { size: 10 }),
162        new CylinderPointMarker3D(wasmContext, { size: 10 }),
163        new PyramidPointMarker3D(wasmContext, { size: 10 }),
164    ];
165
166    const lifeExpectancy = [30, 40, 50, 60, 70, 80, 90, 100];
167    const gdpPerCapita = [5000, 10_000, 15_000, 20_000, 25_000, 30_000, 35_000, 40_000];
168    const year = [1972, 1977, 1982, 1987, 1992, 1997, 2002, 2007];
169
170    const metadata = [
171        { markerType: "EllipsePointMarker3D", pointScale: 1, vertexColor: 4284988847, color: "#67BDAF" },
172        { markerType: "TrianglePointMarker3D", pointScale: 1, vertexColor: 4292639081, color: "#DC7969" },
173        { markerType: "PixelPointMarker3D", pointScale: 1, vertexColor: 4278255615, color: "#FF6B35" },
174        { markerType: "QuadPointMarker", pointScale: 1, vertexColor: 4294934352, color: "#F7931E" },
175        { markerType: "SpherePointMarker3D", pointScale: 2, vertexColor: 4294967040, color: "#FFD23F" },
176        { markerType: "CubePointMarker3D", pointScale: 2, vertexColor: 4278255360, color: "#6BCF7F" },
177        { markerType: "CylinderPointMarker3D", pointScale: 2, vertexColor: 4278190335, color: "#4D96FF" },
178        { markerType: "PyramidPointMarker3D", pointScale: 2, vertexColor: 4286578816, color: "#9B59B6" },
179    ];
180
181    // Create individual series for each data point with different markers
182    for (let i = 0; i < lifeExpectancy.length; i++) {
183        const renderableSeries = new ScatterRenderableSeries3D(wasmContext, {
184            opacity: 0.9,
185            dataSeries: new XyzDataSeries3D(wasmContext, {
186                xValues: [lifeExpectancy[i]],
187                yValues: [gdpPerCapita[i]],
188                zValues: [year[i]],
189                metadata: [metadata[i]],
190            }),
191            pointMarker: pointMarkers[i % pointMarkers.length],
192        });
193
194        sciChart3DSurface.renderableSeries.add(renderableSeries);
195    }
196
197    // update axis title color based on selected axis
198    const updateAxisTitleColor = (axis?: TAxis) => {
199        const SELECTED_AXIS_COLOR = currentTheme === EThemeProviderType.Light ? "#000000" : "#FFFFFF";
200        const UNSELECTED_AXIS_COLOR = "#777777";
201        if (axis === "x" || !axis) {
202            sciChart3DSurface.xAxis.titleStyle.color = SELECTED_AXIS_COLOR;
203            sciChart3DSurface.xAxis.labelStyle.color = SELECTED_AXIS_COLOR;
204
205            sciChart3DSurface.yAxis.titleStyle.color = UNSELECTED_AXIS_COLOR;
206            sciChart3DSurface.zAxis.titleStyle.color = UNSELECTED_AXIS_COLOR;
207            sciChart3DSurface.yAxis.labelStyle.color = UNSELECTED_AXIS_COLOR;
208            sciChart3DSurface.zAxis.labelStyle.color = UNSELECTED_AXIS_COLOR;
209        }
210        if (axis === "y" || !axis) {
211            sciChart3DSurface.yAxis.titleStyle.color = SELECTED_AXIS_COLOR;
212            sciChart3DSurface.yAxis.labelStyle.color = SELECTED_AXIS_COLOR;
213
214            sciChart3DSurface.xAxis.titleStyle.color = UNSELECTED_AXIS_COLOR;
215            sciChart3DSurface.zAxis.titleStyle.color = UNSELECTED_AXIS_COLOR;
216            sciChart3DSurface.xAxis.labelStyle.color = UNSELECTED_AXIS_COLOR;
217            sciChart3DSurface.zAxis.labelStyle.color = UNSELECTED_AXIS_COLOR;
218        }
219        if (axis === "z" || !axis) {
220            sciChart3DSurface.zAxis.titleStyle.color = SELECTED_AXIS_COLOR;
221            sciChart3DSurface.zAxis.labelStyle.color = SELECTED_AXIS_COLOR;
222
223            sciChart3DSurface.xAxis.titleStyle.color = UNSELECTED_AXIS_COLOR;
224            sciChart3DSurface.yAxis.titleStyle.color = UNSELECTED_AXIS_COLOR;
225            sciChart3DSurface.xAxis.labelStyle.color = UNSELECTED_AXIS_COLOR;
226            sciChart3DSurface.yAxis.labelStyle.color = UNSELECTED_AXIS_COLOR;
227        }
228    };
229    updateAxisTitleColor("x");
230
231    const enableGridBands = (enable: boolean, axis: TAxis) => {
232        getAxis(axis).drawMajorBands = enable;
233    };
234
235    const enableMajorGridLines = (enable: boolean, axis: TAxis) => {
236        getAxis(axis).drawMajorGridLines = enable;
237    };
238    const enableMinorGridLines = (enable: boolean, axis: TAxis) => {
239        getAxis(axis).drawMinorGridLines = enable;
240    };
241
242    const setLabelOrientationMode = (mode: E3DLabelOrientationMode, axis: TAxis) => {
243        getAxis(axis).labelOrientationMode = mode;
244    };
245
246    let currentTheme: EThemeProviderType = EThemeProviderType.Navy;
247    const lightTheme = new SciChartJSLightTheme();
248    const darkTheme = new SciChartJSDarkTheme();
249    const darkThemeV2 = new SciChartJSDarkv2Theme();
250    const navyTheme = new SciChartJsNavyTheme();
251
252    const setTheme = (themeName: EThemeProviderType) => {
253        switch (themeName) {
254            case EThemeProviderType.Light:
255                sciChart3DSurface.applyTheme(lightTheme);
256                currentTheme = EThemeProviderType.Light;
257                break;
258            case EThemeProviderType.Dark:
259                sciChart3DSurface.applyTheme(darkTheme);
260                currentTheme = EThemeProviderType.Dark;
261                break;
262            case EThemeProviderType.DarkV2:
263                sciChart3DSurface.applyTheme(darkThemeV2);
264                currentTheme = EThemeProviderType.DarkV2;
265                break;
266            case EThemeProviderType.Navy:
267            default:
268                sciChart3DSurface.applyTheme(navyTheme);
269                currentTheme = EThemeProviderType.Navy;
270                break;
271        }
272        updateAxisTitleColor();
273    };
274
275    const setAxisBandsFill = (color: string, axis: TAxis) => {
276        getAxis(axis).axisBandsFill = color;
277    };
278
279    const setMajorGridLineColor = (color: string, axis: TAxis) => {
280        getAxis(axis).majorGridLineStyle = { color };
281    };
282
283    const setMinorGridLineColor = (color: string, axis: TAxis) => {
284        getAxis(axis).minorGridLineStyle = { color };
285    };
286
287    const controls = {
288        setTheme,
289        setTitleOffset,
290        setTickLabelsOffset,
291        enableGridBands,
292        setAxisLabelFontSize,
293        enableMajorGridLines,
294        enableMinorGridLines,
295        setLabelOrientationMode,
296        updateAxisTitleColor,
297        setVisibilityMode,
298        setDrawTitlesMode,
299        setDrawLabelsMode,
300        setIsPlaneVisible,
301        setPlaneBackground,
302        setAxisBandsFill,
303        setMajorGridLineColor,
304        setMinorGridLineColor,
305    };
306
307    return { sciChartSurface: sciChart3DSurface, wasmContext, controls };
308};
309

3D Styling Demo Chart with JavaScript

Overview

This example demonstrates advanced 3D chart styling capabilities built with SciChart.js using JavaScript. It showcases a comprehensive styling demo featuring multiple point marker types, axis styling controls, and interactive styling features. The example illustrates how to create visually rich 3D charts with extensive customization options without relying on frameworks such as Angular or React.

Technical Implementation

The core of the implementation is the creation of a SciChart 3D surface using the Creating your first SciChartSurface3D guide. The example sets up a custom 3D world with defined dimensions and configures the camera for optimal viewing. Interaction is enhanced by modifiers such as the MouseWheelZoomModifier3D, OrbitModifier3D (see OrbitModifier3D for details), and ResetCamera3DModifier which enable intuitive zooming, panning, and orbiting around the data. The chart features eight different 3D Point Markers including EllipsePointMarker3D, TrianglePointMarker3D, SpherePointMarker3D, CubePointMarker3D, and more, each with unique styling and metadata. Axis selection is shown by the label font color and plane selection uses axisPlaneBackgroundFill.

Features and Capabilities

Key features include multiple point marker types with individual styling, comprehensive axis styling controls, and interactive plane visibility management. The example demonstrates how to customize axis planes with different visibility modes, label drawing modes, and title positioning. Advanced styling options include grid bands, major grid lines, label orientation modes, and dynamic color theming. Each data point is rendered with unique metadata including custom colors and scaling factors.

Integration and Best Practices

This implementation serves as a comprehensive template for integrating advanced 3D chart styling into applications using only JavaScript. Best practices demonstrated here include modular styling control functions, and organized axis configuration. The example shows how to create reusable styling functions for different chart elements and how to manage complex 3D chart interactions. Developers can use these techniques along with detailed SciChart.js documentation to create highly customized and visually appealing 3D charts.

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