React Choropleth Map Example

Demonstrates how to create a React Choropleth map, a type of thematic map where areas are shaded or patterned in proportion to the value of a variable being represented, using our FastTriangleRenderableSeries.

New South Wales - 8,511,151Victoria - 7,012,962Queensland - 5,608,666Western Australia - 2,981,752South Australia - 1,882,722Tasmania - 575,959Australian Capital Territory - 475,644Northern Territory - 255,559
src/drawExample.ts
import {
    ZoomExtentsModifier,
    ZoomPanModifier,
    NumericAxis,
    SciChartSurface,
    NumberRange,
    XyDataSeries,
    ETriangleSeriesDrawMode,
    FastTriangleRenderableSeries,
    MouseWheelZoomModifier,
    FastBubbleRenderableSeries,
    EllipsePointMarker,
    XyzDataSeries,
    IPointMetadata,
    EHorizontalTextPosition,
    Thickness,
    EVerticalTextPosition,
    FastLineRenderableSeries,
} from "scichart";

import { appTheme } from "./appTheme";

import { getMinMax, interpolateColor, keyData, australiaData, preserveAspectRatio } from "./helpers";

import { australianCities } from "./australiaData";

type Keytype = "population" | "population_density" | "area_km2";

const dataArray: { name: string; areaData: number[][] }[] = [];
const outlines: number[][][] = [];

function setMapJson(mapJson: any) {
    dataArray.length = 0;
    outlines.length = 0;
    mapJson.forEach((d: any) => {
        outlines.push(d.outline);
        dataArray.push({ name: d.name, areaData: d.areaData });
    });
}

export const drawExample = async (rootElement: string | HTMLDivElement) => {
    // Create a SciChartSurface
    const { wasmContext, sciChartSurface } = await SciChartSurface.create(rootElement, {
        theme: appTheme.SciChartJsTheme,
    });

    const growBy = new NumberRange(0.1, 0.1);

    sciChartSurface.xAxes.add(new NumericAxis(wasmContext, { growBy, isVisible: true }));
    sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { growBy, isVisible: true }));

    const xAxis = sciChartSurface.xAxes.get(0);
    const yAxis = sciChartSurface.yAxes.get(0);

    let firstTime = true;

    const setMap = (key: Keytype) => {
        sciChartSurface.renderableSeries.clear(true);

        const [min, max] = getMinMax(key, australiaData);

        const series = dataArray.map((d, i) => {
            const dataSeries = new XyDataSeries(wasmContext, {
                xValues: d.areaData.map((p) => p[0]),
                yValues: d.areaData.map((p) => p[1]),
            });

            const triangleSeries = new FastTriangleRenderableSeries(wasmContext, {
                dataSeries: dataSeries,
                drawMode: ETriangleSeriesDrawMode.List,
                fill: interpolateColor(min, max, keyData[d.name][key]),
                opacity: 0.9,
            });

            return triangleSeries;
        });

        sciChartSurface.renderableSeries.add(...series);

        // outline
        const outlinesSC = outlines.map((outline) => {
            const xVals = outline.map((d) => d[0]);
            const yVals = outline.map((d) => d[1]);

            //FastMountainRenderableSeries
            const lineSeries = new FastLineRenderableSeries(wasmContext, {
                dataSeries: new XyDataSeries(wasmContext, {
                    xValues: xVals,
                    yValues: yVals,
                }),
                stroke: "#FFFFFF",
                strokeThickness: 1,
                opacity: 1,
            });

            return lineSeries;
        });

        sciChartSurface.renderableSeries.add(...outlinesSC);

        // cities
        const cLongitude = australianCities.map((d) => d.longitude);
        const clatitude = australianCities.map((d) => d.latitude);
        const cSize = australianCities.map((d) => 5);
        const cMetadata = australianCities.map((d) => d) as unknown as IPointMetadata[];

        const citiesSeries = new FastBubbleRenderableSeries(wasmContext, {
            pointMarker: new EllipsePointMarker(wasmContext, {
                width: 64,
                height: 64,
                fill: appTheme.ForegroundColor,
                strokeThickness: 0,
            }),
            dataSeries: new XyzDataSeries(wasmContext, {
                xValues: cLongitude,
                yValues: clatitude,
                zValues: cSize,
                metadata: cMetadata,
            }),
            dataLabels: {
                verticalTextPosition: EVerticalTextPosition.Above,
                horizontalTextPosition: EHorizontalTextPosition.Right,
                style: {
                    fontFamily: "Arial",
                    fontSize: 14,
                    padding: new Thickness(0, 0, 3, 3),
                },
                color: appTheme.TextColor,
                metaDataSelector: (md) => {
                    const metadata = md as unknown as { name: string };
                    return metadata.name.toString();
                },
            },
        });
        sciChartSurface.renderableSeries.add(citiesSeries);

        if (firstTime) {
            sciChartSurface.zoomExtents();
            firstTime = false;
        }
    };

    sciChartSurface.preRender.subscribe(() => {
        const result = preserveAspectRatio(
            sciChartSurface.viewRect.width,
            sciChartSurface.viewRect.height,
            xAxis.visibleRange.min,
            xAxis.visibleRange.max,
            yAxis.visibleRange.min,
            yAxis.visibleRange.max
        );

        xAxis.visibleRange = new NumberRange(result.minVisibleX, result.maxVisibleX);
        yAxis.visibleRange = new NumberRange(result.minVisibleY, result.maxVisibleY);
    });

    // Add zoom/pan controls
    sciChartSurface.chartModifiers.add(
        new ZoomExtentsModifier(),
        new ZoomPanModifier({ enableZoom: true }),
        new MouseWheelZoomModifier()
    );

    return { wasmContext, sciChartSurface, setMap, setMapJson };
};

Map Example - React

Overview

This React example showcases an interactive Australia map using SciChart.js, wrapped in a SciChartReact component. It demonstrates geographic data visualization with React hooks integration.

Technical Implementation

The chart uses FastTriangleRenderableSeries in List draw mode to render state polygons. The React component passes the drawExample function to SciChartReact for initialization. State management for metric selection is handled externally. This example fetches australiaConverted.json from server. australiaConverted.json is array of objects and each object contains 'name', 'outline' and 'areaData'.

  • name is string that contains name of the location

  • outline is array of arrays that represent longitude and latitude of points that represent outline of area

  • areaData is array of arrays that represent series of coordinate points that form triangles used by SciChart's FastTriangleRenderableSeries to create shapes that represent area

areaData is generated using poly2tri - https://github.com/r3mi/poly2tri.js, a 2D constrained Delaunay triangulation library from GeoJSON representation of Australia map

Features and Capabilities

The implementation features dynamic data binding for metric visualization and preserves aspect ratio during resizing. City markers with interactive labels are implemented using EllipsePointMarker.

Integration and Best Practices

The example demonstrates proper React integration by separating chart logic from presentation. The async initialization pattern follows SciChart's React integration guidelines.