Creates many React Polar Line Charts using SciChart.js, with: data labels, line interpolation, pointMarkers, gradient stroke, startup animations.
drawExample.ts
index.tsx
theme.ts
1import {
2 EAxisAlignment,
3 EllipsePointMarker,
4 EPolarAxisMode,
5 NumberRange,
6 PolarNumericAxis,
7 SciChartPolarSurface,
8 Thickness,
9 XyDataSeries,
10 PolarPanModifier,
11 PolarMouseWheelZoomModifier,
12 RadianLabelProvider,
13 PolarLineRenderableSeries,
14 PolarZoomExtentsModifier,
15 SweepAnimation,
16 DefaultPaletteProvider,
17 EStrokePaletteMode,
18 parseColorToUIntArgb,
19 EHorizontalTextPosition,
20 EVerticalTextPosition,
21 EDataLabelSkipMode,
22 PolarCursorModifier,
23} from "scichart";
24import { appTheme } from "../../../theme";
25
26const COMMON_POLAR_SURFACE_OPTIONS = {
27 theme: appTheme.SciChartJsTheme,
28 padding: new Thickness(0, 0, 0, 0),
29 titleStyle: {
30 fontSize: 18,
31 },
32};
33
34const COMMON_ANGULAR_AXIS_OPTIONS = {
35 polarAxisMode: EPolarAxisMode.Angular,
36 axisAlignment: EAxisAlignment.Top,
37
38 drawMinorGridLines: false,
39 drawMinorTickLines: false,
40 drawMajorTickLines: false,
41
42 labelPrecision: 0,
43 useNativeText: true,
44};
45
46const COMMON_RADIAL_AXIS_OPTIONS = {
47 polarAxisMode: EPolarAxisMode.Radial,
48 axisAlignment: EAxisAlignment.Left,
49
50 drawMinorGridLines: false,
51 drawMinorTickLines: false,
52 drawMajorTickLines: false,
53
54 labelPrecision: 0,
55 useNativeText: true,
56
57 // zoomExtentsToInitialRange: true,
58};
59
60export const getChartsInitializationAPI = () => {
61 const line1 = async (rootElement: string | HTMLDivElement) => {
62 const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
63 ...COMMON_POLAR_SURFACE_OPTIONS,
64 title: "Simple Polar Lines",
65 });
66
67 // Add the yAxis
68 const radialYAxis = new PolarNumericAxis(wasmContext, {
69 ...COMMON_RADIAL_AXIS_OPTIONS,
70
71 autoTicks: false,
72 majorDelta: 2,
73
74 startAngle: Math.PI / 2, // place labels at 12 o'clock
75 });
76 sciChartSurface.yAxes.add(radialYAxis);
77
78 // Add the xAxis
79 const angularXAxis = new PolarNumericAxis(wasmContext, {
80 ...COMMON_ANGULAR_AXIS_OPTIONS,
81
82 autoTicks: false,
83 majorDelta: 30,
84
85 visibleRange: new NumberRange(0, 360),
86 labelPostfix: "°",
87
88 startAngle: Math.PI / 2, // Start drawing at 12 o'clock
89 flippedCoordinates: true, // go clockwise
90
91 zoomExtentsToInitialRange: true, // make sure the visibleRange stays fixed, in `zoomExtents` event case
92 });
93 sciChartSurface.xAxes.add(angularXAxis);
94
95 // Add SERIES
96 const xValues = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300];
97 const polarLine1 = new PolarLineRenderableSeries(wasmContext, {
98 dataSeries: new XyDataSeries(wasmContext, {
99 xValues,
100 yValues: [0, 1, 2, 3, 4, 5, 6, 4, 5, 3, 3],
101 }),
102 stroke: appTheme.VividOrange,
103 strokeThickness: 4,
104 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
105 });
106
107 const polarLine2 = new PolarLineRenderableSeries(wasmContext, {
108 dataSeries: new XyDataSeries(wasmContext, {
109 xValues,
110 yValues: [2, 3, 4, 3, 2, 3, 4, 5, 6, 5, 4],
111 }),
112 stroke: appTheme.VividTeal + "88",
113 strokeThickness: 4,
114 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
115 });
116
117 sciChartSurface.renderableSeries.add(polarLine1, polarLine2);
118
119 sciChartSurface.chartModifiers.add(
120 new PolarPanModifier(),
121 new PolarZoomExtentsModifier(),
122 new PolarMouseWheelZoomModifier()
123 );
124
125 return { sciChartSurface, wasmContext };
126 };
127
128 const line2 = async (rootElement: string | HTMLDivElement) => {
129 const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
130 ...COMMON_POLAR_SURFACE_OPTIONS,
131 title: "Line Function Traces",
132 });
133
134 // Add the yAxis
135 const radialYAxis = new PolarNumericAxis(wasmContext, {
136 ...COMMON_RADIAL_AXIS_OPTIONS,
137 drawLabels: false,
138 });
139 sciChartSurface.yAxes.add(radialYAxis);
140
141 // Add the xAxis
142 const angularXAxis = new PolarNumericAxis(wasmContext, {
143 ...COMMON_ANGULAR_AXIS_OPTIONS,
144
145 visibleRange: new NumberRange(0, Math.PI * 2), // Full trigonometric circle
146
147 labelProvider: new RadianLabelProvider({
148 maxDenominator: 6,
149 }),
150 autoTicks: false,
151 majorDelta: Math.PI / 6, // needed by RadianLabelProvider to show PI fractions
152 });
153 sciChartSurface.xAxes.add(angularXAxis);
154
155 function generatePolarTraces(numPoints: number = 300) {
156 const theta: number[] = Array.from({ length: numPoints }, (_, i) => (i / (numPoints - 1)) * (2 * Math.PI));
157
158 // Normalize function
159 function normalizeY(data: number[]) {
160 const minY = Math.min(...data);
161 const maxY = Math.max(...data);
162 return data.map((d) => (d - minY) / (maxY - minY));
163 }
164
165 // Butterfly Curve
166 const butterfly = normalizeY(
167 theta.map((t) => Math.exp(Math.cos(t)) - 2 * Math.cos(4 * t) + Math.pow(Math.sin(t / 12), 5))
168 );
169
170 // Rose Curve
171 const roseCurve = normalizeY(theta.map((t) => Math.cos(12 * t)));
172
173 // Deltoid Curve
174 const deltoid = normalizeY(theta.map((t) => 2 * (1 - Math.cos(2 * t))));
175
176 // Archimedean Spiral
177 const archimedeanSprial = normalizeY(theta.map((t) => t / (2 * Math.PI)));
178
179 return {
180 xValues: theta,
181 data: [
182 {
183 name: "Rose",
184 yValues: roseCurve,
185 color: appTheme.VividTeal + "66",
186 },
187 {
188 name: "Butterfly",
189 yValues: butterfly,
190 color: appTheme.VividOrange,
191 },
192 // {
193 // name: "Deltoid",
194 // yValues: deltoid,
195 // color: appTheme.VividPink,
196 // },
197 // {
198 // name: "Archimedean Spiral",
199 // yValues: archimedeanSprial,
200 // color: appTheme.VividBlue,
201 // },
202 ],
203 };
204 }
205
206 // Add SERIES
207 const TRACES = generatePolarTraces();
208 TRACES.data.forEach((dataset, i) => {
209 const polarLine = new PolarLineRenderableSeries(wasmContext, {
210 dataSeries: new XyDataSeries(wasmContext, {
211 xValues: TRACES.xValues,
212 yValues: dataset.yValues,
213 dataSeriesName: dataset.name,
214 }),
215 stroke: dataset.color,
216 strokeThickness: 4,
217 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
218 });
219 sciChartSurface.renderableSeries.add(polarLine);
220 });
221
222 sciChartSurface.chartModifiers.add(
223 new PolarPanModifier(),
224 new PolarZoomExtentsModifier(),
225 new PolarMouseWheelZoomModifier()
226 );
227
228 return { sciChartSurface, wasmContext };
229 };
230
231 const line3 = async (rootElement: string | HTMLDivElement) => {
232 const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
233 ...COMMON_POLAR_SURFACE_OPTIONS,
234 title: "Interpolation and pointmarkers",
235 });
236
237 const NR_POINTS = 31;
238 const OFFSET = 20;
239
240 // Add the yAxis
241 const radialYAxis = new PolarNumericAxis(wasmContext, {
242 ...COMMON_RADIAL_AXIS_OPTIONS,
243
244 visibleRange: new NumberRange(0, NR_POINTS + OFFSET),
245 zoomExtentsToInitialRange: true,
246 drawLabels: false,
247 });
248 sciChartSurface.yAxes.add(radialYAxis);
249
250 // Add the xAxis
251 const angularXAxis = new PolarNumericAxis(wasmContext, {
252 ...COMMON_ANGULAR_AXIS_OPTIONS,
253 zoomExtentsToInitialRange: true,
254 });
255 sciChartSurface.xAxes.add(angularXAxis);
256
257 // Add SERIES
258 const xValues = Array.from({ length: NR_POINTS }, (_, i) => i);
259
260 const polarLine = new PolarLineRenderableSeries(wasmContext, {
261 dataSeries: new XyDataSeries(wasmContext, {
262 xValues: xValues,
263 yValues: Array.from({ length: NR_POINTS }, (_, i) => i + OFFSET),
264 }),
265 stroke: appTheme.VividTeal + "88",
266 strokeThickness: 4,
267 pointMarker: new EllipsePointMarker(wasmContext, {
268 width: 7,
269 height: 7,
270 stroke: appTheme.VividTeal,
271 fill: appTheme.DarkIndigo,
272 }),
273 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
274 interpolateLine: true,
275 });
276 sciChartSurface.renderableSeries.add(polarLine);
277
278 sciChartSurface.chartModifiers.add(
279 new PolarPanModifier(),
280 new PolarZoomExtentsModifier(),
281 new PolarMouseWheelZoomModifier()
282 );
283
284 sciChartSurface.zoomExtents();
285
286 return { sciChartSurface, wasmContext };
287 };
288
289 const line4 = async (rootElement: string | HTMLDivElement) => {
290 const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
291 ...COMMON_POLAR_SURFACE_OPTIONS,
292 title: "Y Palette Provider",
293 });
294
295 const TOTAL_DEGREES = 45;
296 const POINTS_PER_DEGREE = 2;
297
298 // Add the yAxis
299 const radialYAxis = new PolarNumericAxis(wasmContext, {
300 ...COMMON_RADIAL_AXIS_OPTIONS,
301 visibleRange: new NumberRange(0, 6),
302
303 zoomExtentsToInitialRange: true,
304 autoTicks: false,
305 majorDelta: 1,
306 innerRadius: 0.1,
307 });
308 sciChartSurface.yAxes.add(radialYAxis);
309
310 // Add the xAxis
311 const angularXAxis = new PolarNumericAxis(wasmContext, {
312 ...COMMON_ANGULAR_AXIS_OPTIONS,
313
314 autoTicks: false,
315 majorDelta: 5,
316
317 visibleRange: new NumberRange(0, TOTAL_DEGREES),
318 labelPostfix: "°",
319
320 flippedCoordinates: true, // go clockwise
321 startAngle: 0, // Start drawing at 12 o'clock, since flippedCoordinates == true
322 totalAngle: Math.PI / 2, // Quarter circle
323
324 zoomExtentsToInitialRange: true, // make sure the visibleRange stays fixed, in `zoomExtents` event case
325 });
326 sciChartSurface.xAxes.add(angularXAxis);
327
328 // Custom PaletteProvider for line series which colours datapoints under and above a threshold
329 class ThresholdLinePaletteProvider extends DefaultPaletteProvider {
330 private readonly stroke: number;
331 private readonly rule: (yValue: number) => boolean;
332
333 constructor(stroke: string, rule: (yValue: number) => boolean) {
334 super();
335 this.strokePaletteMode = EStrokePaletteMode.GRADIENT;
336 this.rule = rule;
337 this.stroke = parseColorToUIntArgb(stroke);
338 }
339
340 // This function is called for every data-point.
341 // Return undefined to use the default color for the line,
342 // else, return a custom colour as an ARGB color code, e.g. 0xFFFF0000 is red
343 overrideStrokeArgb(xValue: number, yValue: number, index: number, opacity: number, metadata: any) {
344 return this.rule(yValue) ? this.stroke : undefined;
345 }
346 }
347
348 // Add SERIES
349 const xValues = Array.from({ length: TOTAL_DEGREES * POINTS_PER_DEGREE }, (_, i) => i / POINTS_PER_DEGREE);
350
351 const polarLine1 = new PolarLineRenderableSeries(wasmContext, {
352 dataSeries: new XyDataSeries(wasmContext, {
353 xValues,
354 yValues: Array.from({ length: TOTAL_DEGREES * POINTS_PER_DEGREE }, (_, i) => {
355 return Math.sin((i * Math.PI) / 12) + 4.5;
356 }),
357 }),
358 stroke: appTheme.VividOrange,
359 strokeThickness: 4,
360 paletteProvider: new ThresholdLinePaletteProvider("white", (yValue) => yValue > 4 && yValue < 5),
361 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
362 });
363
364 const polarLine2 = new PolarLineRenderableSeries(wasmContext, {
365 dataSeries: new XyDataSeries(wasmContext, {
366 xValues,
367 yValues: Array.from({ length: TOTAL_DEGREES * POINTS_PER_DEGREE }, (_, i) => {
368 return Math.sin((i * Math.PI) / 12) + 2.5;
369 }),
370 }),
371 stroke: appTheme.VividTeal + "88",
372 strokeThickness: 4,
373 paletteProvider: new ThresholdLinePaletteProvider("white", (yValue) => yValue > 2 && yValue < 3),
374 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
375 });
376 sciChartSurface.renderableSeries.add(polarLine1, polarLine2);
377
378 sciChartSurface.chartModifiers.add(
379 new PolarPanModifier(),
380 new PolarZoomExtentsModifier(),
381 new PolarMouseWheelZoomModifier()
382 );
383
384 return { sciChartSurface, wasmContext };
385 };
386
387 const line5 = async (rootElement: string | HTMLDivElement) => {
388 const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
389 ...COMMON_POLAR_SURFACE_OPTIONS,
390 title: "DataLabels",
391 });
392
393 // Add the yAxis
394 const radialYAxis = new PolarNumericAxis(wasmContext, {
395 ...COMMON_RADIAL_AXIS_OPTIONS,
396
397 // gridlineMode: EPolarGridlineMode.Polygons,
398 drawLabels: false,
399
400 autoTicks: false,
401 majorDelta: 1,
402 visibleRange: new NumberRange(0, 5),
403 zoomExtentsToInitialRange: true,
404 majorGridLineStyle: {
405 color: appTheme.DarkIndigo,
406 strokeThickness: 1,
407 },
408 });
409 sciChartSurface.yAxes.add(radialYAxis);
410
411 // Add the xAxis
412 const angularXAxis = new PolarNumericAxis(wasmContext, {
413 ...COMMON_ANGULAR_AXIS_OPTIONS,
414
415 visibleRange: new NumberRange(0, Math.PI * 2), // Full trigonometric circle
416 zoomExtentsToInitialRange: true,
417
418 labelProvider: new RadianLabelProvider({
419 maxDenominator: 4,
420 labelPrecision: 2,
421 }),
422
423 majorGridLineStyle: {
424 color: appTheme.DarkIndigo,
425 strokeThickness: 1,
426 },
427 autoTicks: false,
428 majorDelta: Math.PI / 4, // needed by RadianLabelProvider to show PI fractions
429 });
430 sciChartSurface.xAxes.add(angularXAxis);
431
432 // Add line:
433 const line = new PolarLineRenderableSeries(wasmContext, {
434 dataSeries: new XyDataSeries(wasmContext, {
435 xValues: Array.from({ length: 9 }, (_, i) => (i * Math.PI) / 4),
436 yValues: [4, 4.2, 3.5, 1.6, 3.8, 4, 1.8, 4, 2],
437 }),
438 stroke: appTheme.VividOrange,
439 strokeThickness: 4,
440 dataLabels: {
441 color: "white",
442 style: {
443 fontSize: 10,
444 },
445 horizontalTextPosition: EHorizontalTextPosition.Center,
446 verticalTextPosition: EVerticalTextPosition.Center,
447 skipMode: EDataLabelSkipMode.ShowAll,
448 },
449 pointMarker: new EllipsePointMarker(wasmContext, {
450 width: 18,
451 height: 18,
452 stroke: appTheme.VividOrange,
453 fill: appTheme.DarkIndigo,
454 strokeThickness: 1,
455 }),
456 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
457 });
458 sciChartSurface.renderableSeries.add(line);
459
460 sciChartSurface.chartModifiers.add(
461 new PolarPanModifier(),
462 new PolarZoomExtentsModifier(),
463 new PolarMouseWheelZoomModifier()
464 );
465
466 return { sciChartSurface, wasmContext };
467 };
468
469 const line6 = async (rootElement: string | HTMLDivElement) => {
470 const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
471 ...COMMON_POLAR_SURFACE_OPTIONS,
472 title: "X Palette Provider",
473 });
474
475 const NR_POINTS = 40;
476 const OFFSET = 30;
477
478 // Add the yAxis
479 const radialYAxis = new PolarNumericAxis(wasmContext, {
480 ...COMMON_RADIAL_AXIS_OPTIONS,
481
482 visibleRange: new NumberRange(0, NR_POINTS + OFFSET),
483 zoomExtentsToInitialRange: true,
484 drawLabels: false,
485 });
486 sciChartSurface.yAxes.add(radialYAxis);
487
488 // Add the xAxis
489 const angularXAxis = new PolarNumericAxis(wasmContext, {
490 ...COMMON_ANGULAR_AXIS_OPTIONS,
491 zoomExtentsToInitialRange: true,
492 flippedCoordinates: true, // go clockwise
493 startAngle: Math.PI / 2, // Start drawing at 12 o'clock
494 });
495 sciChartSurface.xAxes.add(angularXAxis);
496 appTheme.SciChartJsTheme.strokePalette;
497
498 class XLinePaletteProvider extends DefaultPaletteProvider {
499 private readonly _colors = appTheme.SciChartJsTheme.strokePalette as string[];
500
501 constructor() {
502 super();
503 this.strokePaletteMode = EStrokePaletteMode.SOLID;
504 }
505
506 // This function is called for every data-point.
507 // Return undefined to use the default color for the line,
508 // else, return a custom colour as an ARGB color code, e.g. 0xFFFF0000 is red
509 overrideStrokeArgb(xValue: number, yValue: number, index: number, opacity: number, metadata: any) {
510 return parseColorToUIntArgb(this._colors[Math.min(Math.floor(index / 2)) % this._colors.length]);
511 }
512 }
513
514 // Add SERIES
515 const polarLine = new PolarLineRenderableSeries(wasmContext, {
516 dataSeries: new XyDataSeries(wasmContext, {
517 xValues: Array.from({ length: NR_POINTS }, (_, i) => i + 1),
518 yValues: Array.from({ length: NR_POINTS }, (_, i) => i + OFFSET),
519 }),
520 stroke: appTheme.VividTeal,
521 strokeThickness: 4,
522 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
523 paletteProvider: new XLinePaletteProvider(),
524 });
525
526 sciChartSurface.renderableSeries.add(polarLine);
527
528 sciChartSurface.chartModifiers.add(
529 new PolarPanModifier(),
530 new PolarZoomExtentsModifier(),
531 new PolarMouseWheelZoomModifier(),
532 new PolarCursorModifier()
533 );
534
535 sciChartSurface.zoomExtents();
536
537 return { sciChartSurface, wasmContext };
538 };
539
540 return {
541 line1,
542 line2,
543 line3,
544 line4,
545 line5,
546 line6,
547 };
548};
549This React example demonstrates how to integrate SciChart's Polar Line Chart capabilities into a React application using the SciChartReact component. The implementation showcases multiple polar line configurations with React-friendly initialization patterns.
The chart is initialized through the <SciChartReact/> component's initChart prop, which receives an async function that creates and configures the polar surface. The example follows React best practices by:
The implementation leverages SciChartPolarSurface with PolarNumericAxis for coordinate system setup. Animation effects are achieved using SweepAnimation.
The React implementation showcases:

Try the React Polar Spline Line Chart example to see SciChart's GPU-accelerated rendering in action. Choose a cubic spline or polar interpolation. View demo.

Create a React Multi-Cycle Polar Chart to plot data over multiple cycles and visualize patterns over time. This example shows surface temperature by month.

Try the React Polar Bar Chart example to render bars in a polar layout with gradient fills and animations. Use SciChart for seamless integration with React.

Create a React Polar Colum Category chart visualizing UK consumer price changes. Try the demo with a custom positive/negative threshold fill and stroke.

Create a React Polar Range Column Chart with SciChart. This example displays monthly minimum and maximum temperatures within a Polar layout. Try the demo.

View the React Windrose Chart example to display directional data with stacked columns in a polar layout. Try the polar chart demo with customizable labels.

See the React Sunburst Chart example with multiple levels, smooth animation transitions and dynamically updating segment colors. Try the SciChart demo.

View the React Radial Column Chart example to see the difference that SciChart has to offer. Switch radial and angular axes and add interactive modifiers.

This React Stacked Radial Bar Chart example shows Olympic medal data by country. Try the demo for yourself with async initialization and theme application.

The React Polar Area Chart example, also known as Nightingale Rose Chart, renders an area series with polar coordinates with interactive legend controls.

Try the React Stacked Radial Mountain Chart example to show multiple datasets on a polar layout with a stacked mountain series and animated transitions.

Create a React Polar Chart with regular and interpolated error bands. Enhance a standard chart with shaded areas to show upper and lower data boundaries.

Build a React Polar Scatter Chart with this example to render multiple scatter series on radial and angular axes. Try the flexible SciChart demo today.

View the React Polar Radar Chart example. Also known as the Spider Radar Chart, view the scalability and stability that SciChart has to offer. Try demo.

Create React Gauge Charts, including a React Circular Gauge Dashboard, with React-friendly initialization and responsive design. Give the SciChart demo a go.

View React Arc Gauge Charts alongside FIFO Scrolling Charts, all on the same dashboard with real-time, high-performance data rendering. Try the demo.

Try SciChart's React Polar Heatmap example to combine a polar heatmap with a legend component. Supports responsive design and chart and legend separation.

No description available for this example yet

Create a React Polar Partial Arc that bends from a full Polar Circle to a Cartesian-like arc. Try the demo to display an arc segment with Polar coordinates.

Create a React Polar Axis Label with SciChart. This demo shows the various label modes for Polar Axes – all optimised for pan, zoom, and mouse wheel.

View the React Polar Map Example using the SciChartReact component. Display geographic data as color-coded triangles on a polar coordinate system. Try demo.