Angular Polar Sunburst Chart

Creates a Angular Polar Sunburst Chart using SciChart.js, with the following features: DataLabels, Rounded corners, Gradient-palette fill, startup animations.

Fullscreen

Edit

 Edit

Docs

drawExample.ts

angular.ts

theme.ts

sunburstData.ts

SunburstMetadata.ts

Copy to clipboard
Minimise
Fullscreen
1import {
2    PolarColumnRenderableSeries,
3    PolarNumericAxis,
4    SciChartPolarSurface,
5    EPolarAxisMode, 
6    NumberRange, 
7    EAxisAlignment, 
8    EPolarLabelMode,
9    PolarCursorModifier,
10    TCursorTooltipDataTemplate,
11    SeriesInfo,
12    Thickness,
13    EPolarGridlineMode,
14    PolarDataPointSelectionModifier,
15    SciChartJSLightTheme,
16    TSciChart,
17    EColumnMode,
18    XyxDataSeries,
19    EMultiLineAlignment,
20    EColumnDataLabelPosition,
21    EDataPointWidthMode,
22    GenericAnimation,
23    easing,
24    DoubleAnimator,
25    translateToNotScaled,
26    adjustTooltipPosition,
27    calcTooltipSize,
28    CursorTooltipSvgAnnotation,
29    TCursorTooltipSvgTemplate,
30    parseColorToTArgb
31} from "scichart";
32import { appTheme } from "../../../theme";
33import { SunburstMetadata } from "./SunburstMetadata";
34import { SunburstPaletteProvider } from "./SunburstPaletteProvider"
35import { getDataById, getElementById, TLevelDataForChart } from "./sunburstData";
36
37const drawSeriesFn = (
38    wasmContext: TSciChart,
39    xAxis: PolarNumericAxis,
40    yAxis: PolarNumericAxis,
41    sciChartSurface: SciChartPolarSurface,
42    polarLabelMode: EPolarLabelMode,
43    dataPointSelectionModifier: PolarDataPointSelectionModifier,
44    nodeId: number[],
45    selectedElStartX: number,
46    prevNodeId: number[]
47) => {
48    const startAngleDefault = - Math.PI / 2;
49
50    const clearSeriesFn = () => {
51        dataPointSelectionModifier.selectionChanged.unsubscribeAll();
52        sciChartSurface.renderableSeries.asArray().forEach(rs => rs.delete());
53        sciChartSurface.renderableSeries.clear();
54    };
55
56    const level = nodeId.length - 1;
57    const prevLevel = prevNodeId.length - 1;
58    const prevXVisRangeDiff = xAxis.visibleRange.diff;
59
60    const polarColumnMode = EColumnMode.StartEnd;
61    const dataPointWidth = 0.5;
62    const paletteProvider = new SunburstPaletteProvider();
63
64    const createDataFn = (input$: TLevelDataForChart) => {
65        const [xValues$, yValues$, x1Values$] = input$.data;
66        return new XyxDataSeries(wasmContext, {
67            xValues: xValues$,
68            yValues: yValues$,
69            x1Values: x1Values$,
70            metadata: input$.metadata
71        });
72    };
73
74    const levelData = getDataById(nodeId);
75    const rootNode = getElementById(nodeId);
76
77    const redrawSeriesFn = () => {
78        clearSeriesFn();
79        for (let i = 0; i < levelData.length; i++) {
80            const rs$ = new PolarColumnRenderableSeries(wasmContext, {
81                stroke: "black",
82                columnXMode: polarColumnMode,
83                dataLabels: {
84                    style: {
85                        fontSize: 16,
86                        multiLineAlignment: EMultiLineAlignment.Center,
87                        lineSpacing: 8
88                    },
89                    color: "black",
90                    precision: 2,
91                    pointGapThreshold: 0,
92                    skipNumber: 0,
93                    polarLabelMode,
94                    labelYPositionMode: EColumnDataLabelPosition.Position,
95                    labelYPositionMultiplier: 0.5,
96                    metaDataSelector: metadata => {
97                        const md = metadata as SunburstMetadata;
98                        return `${md.title} \n ${md.value}`;
99                    }
100                },
101                dataSeries: createDataFn(levelData[i]),
102                strokeThickness: 2,
103                dataPointWidth,
104                dataPointWidthMode: EDataPointWidthMode.Range,
105                defaultY1: i,
106                paletteProvider: paletteProvider
107            });
108            dataPointSelectionModifier.includeSeries(rs$, true);
109            sciChartSurface.renderableSeries.add(rs$);
110        }
111    };
112
113    const drillDownAnimationFn = (isReverse$: boolean, onCompleteFn$: () => void = () => undefined) => {
114        const xMin$ = 0; // always zero
115        const xMax0$ = prevXVisRangeDiff;
116        const xMax1$ = rootNode.value;
117
118        const startAngle0$ = isReverse$
119            ? startAngleDefault
120            : startAngleDefault + (2 * Math.PI * selectedElStartX) / xAxis.visibleRange.diff;
121        let startAngle1$: number;
122        if (isReverse$) {
123            const levelDiff$ = prevLevel - level;
124            const element$ = levelData[levelDiff$].metadata.find(a => a.id.toString() === prevNodeId.toString());
125            startAngle1$ = startAngleDefault + (2 * Math.PI * element$.start) / rootNode.value;
126        } else {
127            startAngle1$ = startAngleDefault;
128        }
129
130        const yMin0$ = isReverse$ ? 0 : prevLevel - level;
131        const yMin1$ = isReverse$ ? level - prevLevel : 0;
132
133        const from$ = { x1: xMax0$, x2: startAngle0$, y1: yMin0$, y2: 0 };
134        const to$ = { x1: xMax1$, x2: startAngle1$, y1: yMin1$, y2: 0 };
135
136        const sweepAnimation = new GenericAnimation({
137            from: from$,
138            to: to$,
139            duration: 2000,
140            ease: easing.inOutSine,
141            onAnimate: (from, to, progress) => {
142                const xMaxCur = DoubleAnimator.interpolate(from.x1, to.x1, progress);
143                const startAngleCur = DoubleAnimator.interpolate(from.x2, to.x2, progress);
144                const yMinCur = DoubleAnimator.interpolate(from.y1, to.y1, progress);
145                const yMaxCur = yMinCur + 4;
146                xAxis.visibleRange = new NumberRange(xMin$, xMaxCur);
147                xAxis.startAngle = startAngleCur;
148                yAxis.visibleRange = new NumberRange(yMinCur, yMaxCur);
149            },
150            onCompleted: () => {
151                onCompleteFn$();
152            }
153        });
154        sciChartSurface.addAnimation(sweepAnimation);
155    };
156
157    const subscribeFn = () => {
158        dataPointSelectionModifier.selectionChanged.subscribe(args => {
159            const selectedDataPoint = args.selectedDataPoints[0];
160            if (selectedDataPoint) {
161                const { yValue } = selectedDataPoint;
162                const md = selectedDataPoint?.metadata as SunburstMetadata;
163                const { id } = md;
164                const newId = [...id];
165                if (yValue === 1 && id.length > 1) {
166                    newId.pop();
167                }
168                drawSeriesFn(
169                    wasmContext,
170                    xAxis,
171                    yAxis,
172                    sciChartSurface,
173                    polarLabelMode,
174                    dataPointSelectionModifier,
175                    newId,
176                    md.start,
177                    nodeId
178                );
179            }
180        });
181    };
182
183    if (level < prevLevel) {
184        drillDownAnimationFn(true, () => {
185            redrawSeriesFn();
186            xAxis.startAngle = startAngleDefault;
187            yAxis.visibleRange = new NumberRange(0, 4);
188            subscribeFn();
189        });
190    } else if (level > prevLevel) {
191        redrawSeriesFn();
192        drillDownAnimationFn(false);
193        subscribeFn();
194    } else {
195        xAxis.startAngle = startAngleDefault;
196        xAxis.visibleRange = new NumberRange(0, rootNode.value);
197        yAxis.visibleRange = new NumberRange(0, 4);
198        redrawSeriesFn();
199        subscribeFn();
200    }
201};
202
203export const drawExample = async (rootElement: string | HTMLDivElement) => {
204    const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
205        theme: appTheme.SciChartJsTheme
206    });
207
208    const startAngle = -Math.PI / 2;
209    const totalAngle = 2 * Math.PI;
210
211    const xAxis = new PolarNumericAxis(wasmContext, {
212        isVisible: false,
213        polarAxisMode: EPolarAxisMode.Angular,
214        axisAlignment: EAxisAlignment.Top,
215        visibleRange: new NumberRange(0, 65),
216        startAngle,
217        totalAngle
218    });
219    xAxis.polarLabelMode = EPolarLabelMode.Parallel;
220    sciChartSurface.xAxes.add(xAxis);
221
222    const yAxis = new PolarNumericAxis(wasmContext, {
223        isVisible: false,
224        polarAxisMode: EPolarAxisMode.Radial,
225        axisAlignment: EAxisAlignment.Right,
226        visibleRange: new NumberRange(0, 6),
227        flippedCoordinates: false,
228        startAngle,
229        totalAngle,
230    });
231    sciChartSurface.yAxes.add(yAxis);
232
233
234    const dataPointSelectionModifier = new PolarDataPointSelectionModifier({
235        allowClickSelect: true,
236        allowDragSelect: true,
237        selectionStroke: "red",
238        selectionFill: "#ff879f33"
239    });
240
241    drawSeriesFn(
242        wasmContext, 
243        xAxis, 
244        yAxis, 
245        sciChartSurface, 
246        EPolarLabelMode.Parallel, 
247        dataPointSelectionModifier, 
248        [0], 
249        0, 
250        [0]
251    );
252
253    const tooltipDataTemplate: TCursorTooltipDataTemplate = (seriesInfos: SeriesInfo[], tooltipTitle: string) => {
254        const res: string[] = [];
255        seriesInfos.forEach(si => {
256            if (si.isHit) {
257                const md = si.pointMetadata as SunburstMetadata;
258                res.push(`Name: ${md.title}`);
259                res.push(`Value: ${md.value}`);
260            }
261        });
262        return res;
263    };
264
265    sciChartSurface.chartModifiers.add(
266        dataPointSelectionModifier,
267        new PolarCursorModifier({
268            showTooltip: true,
269            showCircularLine: false,
270            showRadialLine: false,
271            tooltipDataTemplate,
272        })
273    );
274
275    return { sciChartSurface, wasmContext };
276};

See Also: Polar Charts (20 Demos)

Angular Polar Line Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Line Chart

Angular Polar Line Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Spline Line Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Spline Line Chart

Angular Polar Spline Line Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Line Temperature Average | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Line Temperature Average

Angular Polar Line Temperature Average demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Column Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Column Chart

Angular Polar Column Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Column Category Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Column Category Chart

Angular Polar Column Category Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Range Column Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Range Column Chart

Angular Polar Range Column Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Windrose Column Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Windrose Column Chart

Angular Windrose Column Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Radial Column Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Radial Column Chart

Angular Radial Column Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Stacked Radial Column Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Stacked Radial Column Chart

Angular Stacked Radial Column Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Mountain Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Mountain Chart

Angular Polar Mountain Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Stacked Mountain Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Stacked Mountain Chart

Angular Polar Stacked Mountain Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Band Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Band Chart

Angular Polar Band Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Scatter Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Scatter Chart

Angular Polar Scatter Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Radar Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Radar Chart

Angular Polar Radar Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Gauge Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Gauge Chart

Angular Polar Gauge Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Gauge Fifo Dashboard | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Gauge Fifo Dashboard

Angular Polar Gauge Fifo Dashboard demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Uniform Heatmap Chart | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Uniform Heatmap Chart

Angular Polar Uniform Heatmap Chart demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Ultrasound Heatmap | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Ultrasound Heatmap

Angular Polar Ultrasound Heatmap demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Partial Arc | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Partial Arc

Angular Polar Partial Arc demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

Angular Polar Label Modes | JavaScript Charts | SciChart.js | SciChart.js Demo

Angular Polar Label Modes

Angular Polar Label Modes demo by SciChart supports gradient fill and paletteproviders for more custom coloring options. Get your free demo now.

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