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 whiteColor = "#FFFFFFFD"
291 const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
292 ...COMMON_POLAR_SURFACE_OPTIONS,
293 title: "Y Palette Provider",
294 });
295
296 const TOTAL_DEGREES = 45;
297 const POINTS_PER_DEGREE = 2;
298
299 // Add the yAxis
300 const radialYAxis = new PolarNumericAxis(wasmContext, {
301 ...COMMON_RADIAL_AXIS_OPTIONS,
302 visibleRange: new NumberRange(0, 6),
303
304 zoomExtentsToInitialRange: true,
305 autoTicks: false,
306 majorDelta: 1,
307 innerRadius: 0.1,
308 });
309 sciChartSurface.yAxes.add(radialYAxis);
310
311 // Add the xAxis
312 const angularXAxis = new PolarNumericAxis(wasmContext, {
313 ...COMMON_ANGULAR_AXIS_OPTIONS,
314
315 autoTicks: false,
316 majorDelta: 5,
317
318 visibleRange: new NumberRange(0, TOTAL_DEGREES),
319 labelPostfix: "°",
320
321 flippedCoordinates: true, // go clockwise
322 startAngle: 0, // Start drawing at 12 o'clock, since flippedCoordinates == true
323 totalAngle: Math.PI / 2, // Quarter circle
324
325 zoomExtentsToInitialRange: true, // make sure the visibleRange stays fixed, in `zoomExtents` event case
326 });
327 sciChartSurface.xAxes.add(angularXAxis);
328
329 // Custom PaletteProvider for line series which colours datapoints under and above a threshold
330 class ThresholdLinePaletteProvider extends DefaultPaletteProvider {
331 private readonly stroke: number;
332 private readonly rule: (yValue: number) => boolean;
333
334 constructor(stroke: string, rule: (yValue: number) => boolean) {
335 super();
336 this.strokePaletteMode = EStrokePaletteMode.GRADIENT;
337 this.rule = rule;
338 this.stroke = parseColorToUIntArgb(stroke);
339 }
340
341 // This function is called for every data-point.
342 // Return undefined to use the default color for the line,
343 // else, return a custom colour as an ARGB color code, e.g. 0xFFFF0000 is red
344 overrideStrokeArgb(xValue: number, yValue: number, index: number, opacity: number, metadata: any) {
345 return this.rule(yValue) ? this.stroke : undefined;
346 }
347 }
348
349 // Add SERIES
350 const xValues = Array.from({ length: TOTAL_DEGREES * POINTS_PER_DEGREE }, (_, i) => i / POINTS_PER_DEGREE);
351
352 const polarLine1 = new PolarLineRenderableSeries(wasmContext, {
353 dataSeries: new XyDataSeries(wasmContext, {
354 xValues,
355 yValues: Array.from({ length: TOTAL_DEGREES * POINTS_PER_DEGREE }, (_, i) => {
356 return Math.sin((i * Math.PI) / 12) + 4.5;
357 }),
358 }),
359 stroke: appTheme.VividOrange,
360 strokeThickness: 4,
361 paletteProvider: new ThresholdLinePaletteProvider(whiteColor, (yValue) => yValue > 4 && yValue < 5),
362 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
363 });
364
365 const polarLine2 = new PolarLineRenderableSeries(wasmContext, {
366 dataSeries: new XyDataSeries(wasmContext, {
367 xValues,
368 yValues: Array.from({ length: TOTAL_DEGREES * POINTS_PER_DEGREE }, (_, i) => {
369 return Math.sin((i * Math.PI) / 12) + 2.5;
370 }),
371 }),
372 stroke: appTheme.VividTeal + "88",
373 strokeThickness: 4,
374 paletteProvider: new ThresholdLinePaletteProvider(whiteColor, (yValue) => yValue > 2 && yValue < 3),
375 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
376 });
377 sciChartSurface.renderableSeries.add(polarLine1, polarLine2);
378
379 sciChartSurface.chartModifiers.add(
380 new PolarPanModifier(),
381 new PolarZoomExtentsModifier(),
382 new PolarMouseWheelZoomModifier()
383 );
384
385 return { sciChartSurface, wasmContext };
386 };
387
388 const line5 = async (rootElement: string | HTMLDivElement) => {
389 const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
390 ...COMMON_POLAR_SURFACE_OPTIONS,
391 title: "DataLabels",
392 });
393
394 // Add the yAxis
395 const radialYAxis = new PolarNumericAxis(wasmContext, {
396 ...COMMON_RADIAL_AXIS_OPTIONS,
397
398 // gridlineMode: EPolarGridlineMode.Polygons,
399 drawLabels: false,
400
401 autoTicks: false,
402 majorDelta: 1,
403 visibleRange: new NumberRange(0, 5),
404 zoomExtentsToInitialRange: true,
405 majorGridLineStyle: {
406 // color: appTheme.DarkIndigo,
407 strokeThickness: 1,
408 },
409 });
410 sciChartSurface.yAxes.add(radialYAxis);
411
412 // Add the xAxis
413 const angularXAxis = new PolarNumericAxis(wasmContext, {
414 ...COMMON_ANGULAR_AXIS_OPTIONS,
415
416 visibleRange: new NumberRange(0, Math.PI * 2), // Full trigonometric circle
417 zoomExtentsToInitialRange: true,
418
419 labelProvider: new RadianLabelProvider({
420 maxDenominator: 4,
421 labelPrecision: 2,
422 }),
423
424 majorGridLineStyle: {
425 // color: appTheme.DarkIndigo,
426 strokeThickness: 1,
427 },
428 autoTicks: false,
429 majorDelta: Math.PI / 4, // needed by RadianLabelProvider to show PI fractions
430 });
431 sciChartSurface.xAxes.add(angularXAxis);
432
433 // Add line:
434 const line = new PolarLineRenderableSeries(wasmContext, {
435 dataSeries: new XyDataSeries(wasmContext, {
436 xValues: Array.from({ length: 9 }, (_, i) => (i * Math.PI) / 4),
437 yValues: [4, 4.2, 3.5, 1.6, 3.8, 4, 1.8, 4, 2],
438 }),
439 stroke: appTheme.VividOrange,
440 strokeThickness: 4,
441 dataLabels: {
442 color: "white",
443 style: {
444 fontSize: 10,
445 },
446 horizontalTextPosition: EHorizontalTextPosition.Center,
447 verticalTextPosition: EVerticalTextPosition.Center,
448 skipMode: EDataLabelSkipMode.ShowAll,
449 },
450 pointMarker: new EllipsePointMarker(wasmContext, {
451 width: 18,
452 height: 18,
453 stroke: appTheme.VividOrange,
454 fill: appTheme.DarkIndigo,
455 strokeThickness: 1,
456 }),
457 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
458 });
459 sciChartSurface.renderableSeries.add(line);
460
461 sciChartSurface.chartModifiers.add(
462 new PolarPanModifier(),
463 new PolarZoomExtentsModifier(),
464 new PolarMouseWheelZoomModifier()
465 );
466
467 return { sciChartSurface, wasmContext };
468 };
469
470 const line6 = async (rootElement: string | HTMLDivElement) => {
471 const { sciChartSurface, wasmContext } = await SciChartPolarSurface.create(rootElement, {
472 ...COMMON_POLAR_SURFACE_OPTIONS,
473 title: "X Palette Provider",
474 });
475
476 const NR_POINTS = 40;
477 const OFFSET = 30;
478
479 // Add the yAxis
480 const radialYAxis = new PolarNumericAxis(wasmContext, {
481 ...COMMON_RADIAL_AXIS_OPTIONS,
482
483 visibleRange: new NumberRange(0, NR_POINTS + OFFSET),
484 zoomExtentsToInitialRange: true,
485 drawLabels: false,
486 });
487 sciChartSurface.yAxes.add(radialYAxis);
488
489 // Add the xAxis
490 const angularXAxis = new PolarNumericAxis(wasmContext, {
491 ...COMMON_ANGULAR_AXIS_OPTIONS,
492 zoomExtentsToInitialRange: true,
493 flippedCoordinates: true, // go clockwise
494 startAngle: Math.PI / 2, // Start drawing at 12 o'clock
495 });
496 sciChartSurface.xAxes.add(angularXAxis);
497 appTheme.SciChartJsTheme.strokePalette;
498
499 class XLinePaletteProvider extends DefaultPaletteProvider {
500 private readonly _colors = appTheme.SciChartJsTheme.strokePalette as string[];
501
502 constructor() {
503 super();
504 this.strokePaletteMode = EStrokePaletteMode.SOLID;
505 }
506
507 // This function is called for every data-point.
508 // Return undefined to use the default color for the line,
509 // else, return a custom colour as an ARGB color code, e.g. 0xFFFF0000 is red
510 overrideStrokeArgb(xValue: number, yValue: number, index: number, opacity: number, metadata: any) {
511 return parseColorToUIntArgb(this._colors[Math.min(Math.floor(index / 2)) % this._colors.length]);
512 }
513 }
514
515 // Add SERIES
516 const polarLine = new PolarLineRenderableSeries(wasmContext, {
517 dataSeries: new XyDataSeries(wasmContext, {
518 xValues: Array.from({ length: NR_POINTS }, (_, i) => i + 1),
519 yValues: Array.from({ length: NR_POINTS }, (_, i) => i + OFFSET),
520 }),
521 stroke: appTheme.VividTeal,
522 strokeThickness: 4,
523 animation: new SweepAnimation({ duration: 800, fadeEffect: true }),
524 paletteProvider: new XLinePaletteProvider(),
525 });
526
527 sciChartSurface.renderableSeries.add(polarLine);
528
529 sciChartSurface.chartModifiers.add(
530 new PolarPanModifier(),
531 new PolarZoomExtentsModifier(),
532 new PolarMouseWheelZoomModifier(),
533 new PolarCursorModifier()
534 );
535
536 sciChartSurface.zoomExtents();
537
538 return { sciChartSurface, wasmContext };
539 };
540
541 return {
542 line1,
543 line2,
544 line3,
545 line4,
546 line5,
547 line6,
548 };
549};
550This 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.