SciChart.js JavaScript 2D Charts API > 2D Chart Types > Series PaletteProvider API > Per-Point Colouring of Bubble Charts
Per-Point Colouring of Bubble Charts

Colouring Bubble Points Individually with PaletteProvider

It is possible to override the Bubble series point-marker fill & stroke colour on a per-datapoint basis in SciChart.js using the PaletteProvider API.

To use this, we must create a class which implements or confirms to the IPointMarkerPaletteProvider interface. Then, apply this to the XyScatterRenderableSeries.paletteProvider property. This allows you to colour data-points based on values, or custom rules with infinite extensiblity.

Let's start off by creating a PaletteProvider class:

const {
  DefaultPaletteProvider,
  EStrokePaletteMode,
  parseColorToUIntArgb
} = SciChart;

// or, for npm, import { DefaultPaletteProvider, ... } from "scichart"

// Custom PaletteProvider for line series which colours datapoints above a threshold
class BubblePaletteProvider extends DefaultPaletteProvider {

  constructor(fill, rule) {
    super();
    this.strokePaletteMode = EStrokePaletteMode.SOLID;
    this.rule = rule;
    // Use the helper function parseColorToUIntArgb to convert a hex string
    // e.g. #FF00FF77 into ARGB numeric format 0xFF00FF77 expected by scichart
    this.overrideFill = parseColorToUIntArgb(fill);
  }

  // This function is called for every data-point.
  // Return undefined to use the default color for the pointmarker,
  // else, return a custom colour as an ARGB color code, e.g. 0xFFFF0000 is red
  overridePointMarkerArgb(xValue, yValue, index, opacity, metadata) {
    // Draw points outside the range a different color
    if (this.rule(yValue)) {
      return { stroke: this.overrideFill, fill: this.overrideFill }
    }
    // Undefined means use default colors
    return undefined;
  }
}
It is important that overridePointMarkerArgb returns an object containing both stroke and fill, even if stroke is ignored on the bubble series.

 

Next, we can apply the PaletteProvider to a Bubble Series. This can be done both with the programmatic API and the Builder API:

// The BubblePaletteProvider we created before is applied to a FastBubbleRenderableSeries
const bubbleSeries = new FastBubbleRenderableSeries(wasmContext, {
  dataSeries: xyzDataSeries,
  opacity: 1,
  pointMarker: new EllipsePointMarker(wasmContext, {
    // choose a suitably large size for pointmarker. This will  be scaled per-point
    width: 64,
    height: 64,
    strokeThickness: 0,
    fill: "#4682b477"
  }),
  // PaletteProvider feature allows coloring per-point based on a rule
  paletteProvider: new BubblePaletteProvider("Red", yValue => yValue > -0.8)
});

sciChartSurface.renderableSeries.add(bubbleSeries);
// Register the custom BubblePaletteProvider with the chartBuilder
chartBuilder.registerType(EBaseType.PaletteProvider, "BubblePaletteProvider",
    (options) => new BubblePaletteProvider(options.fill, options.rule));

const { wasmContext, sciChartSurface } = await chartBuilder.build2DChart(divElementId, {
  surface: { theme: { type: EThemeProviderType.Dark } },
  series: [
    {
      type: ESeriesType.BubbleSeries,
      xyzData: {
        xValues,
        yValues,
        zValues: sizes
      },
      options: {
        pointMarker: {
          type: EPointMarkerType.Ellipse,
          options: {
            // choose a suitably large size for pointmarker. This will  be scaled per-point
            width: 64,
            height: 64,
            strokeThickness: 0,
            fill: "#4682b477"
          }
        },
        // Now you can instantiate using parameters below
        paletteProvider: {
          type: EPaletteProviderType.Custom,
          customType: "BubblePaletteProvider",
          options: {
            fill: "Red",
            rule: (yValue) => yValue >= -0.8,
          }
        }
        // Note: Assigning an instance is also valid, e.g.
        // paletteProvider: new BubblePaletteProvider("Green", "Red", yValue => yValue >= 4.0)
      }
    }
  ]
});

 

This results in the following output. Values above the threshold are coloured red, while values below this threshold use the default colour.

<div id="scichart-root" ></div>
  
body { margin: 0; }
#scichart-root { width: 100%; height: 100vh; }
  
// #region ExampleA
const {
  DefaultPaletteProvider,
  EStrokePaletteMode,
  parseColorToUIntArgb
} = SciChart;

// or, for npm, import { DefaultPaletteProvider, ... } from "scichart"

// Custom PaletteProvider for line series which colours datapoints above a threshold
class BubblePaletteProvider extends DefaultPaletteProvider {

  constructor(fill, rule) {
    super();
    this.strokePaletteMode = EStrokePaletteMode.SOLID;
    this.rule = rule;
    // Use the helper function parseColorToUIntArgb to convert a hex string
    // e.g. #FF00FF77 into ARGB numeric format 0xFF00FF77 expected by scichart
    this.overrideFill = parseColorToUIntArgb(fill);
  }

  // This function is called for every data-point.
  // Return undefined to use the default color for the pointmarker,
  // else, return a custom colour as an ARGB color code, e.g. 0xFFFF0000 is red
  overridePointMarkerArgb(xValue, yValue, index, opacity, metadata) {
    // Draw points outside the range a different color
    if (this.rule(yValue)) {
      return { stroke: this.overrideFill, fill: this.overrideFill }
    }
    // Undefined means use default colors
    return undefined;
  }
}
// #endregion

async function drawBubbleChartWithPalette(divElementId) {
  // Demonstrates how to create a bubble chart with SciChart.js
  const {
    SciChartSurface,
    NumericAxis,
    XyzDataSeries,
    FastBubbleRenderableSeries,
    EllipsePointMarker,
    SciChartJsNavyTheme,
    ELabelPlacement,
    HorizontalLineAnnotation
  } = SciChart;

  // or, for npm, import { SciChartSurface, ... } from "scichart"

  const { wasmContext, sciChartSurface } = await SciChartSurface.create(divElementId, {
    theme: new SciChartJsNavyTheme()
  });
  sciChartSurface.xAxes.add(new NumericAxis(wasmContext));
  sciChartSurface.yAxes.add(new NumericAxis(wasmContext));

  const xValues = [];
  const yValues = [];
  const sizes = [];
  for(let i = 0; i < 30; i++) {
    xValues.push(i);
    yValues.push(0.2 * Math.sin(i*0.2) - Math.cos(i * 0.04));
    sizes.push(Math.sin(i) * 60 + 3);
  }

  const xyzDataSeries = new XyzDataSeries(wasmContext, {
    xValues,
    yValues,
    zValues: sizes
  });

  // #region ExampleB
  // The BubblePaletteProvider we created before is applied to a FastBubbleRenderableSeries
  const bubbleSeries = new FastBubbleRenderableSeries(wasmContext, {
    dataSeries: xyzDataSeries,
    opacity: 1,
    pointMarker: new EllipsePointMarker(wasmContext, {
      // choose a suitably large size for pointmarker. This will  be scaled per-point
      width: 64,
      height: 64,
      strokeThickness: 0,
      fill: "#4682b477"
    }),
    // PaletteProvider feature allows coloring per-point based on a rule
    paletteProvider: new BubblePaletteProvider("Red", yValue => yValue > -0.8)
  });

  sciChartSurface.renderableSeries.add(bubbleSeries);
  // #endregion

  // Optional: add zooming, panning for the example
  const { MouseWheelZoomModifier, ZoomPanModifier, ZoomExtentsModifier } = SciChart;
  sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier(), new ZoomPanModifier, new ZoomExtentsModifier());

  // Add this label & annotation to the chart
  sciChartSurface.annotations.add(new HorizontalLineAnnotation({ y1: -0.8, stroke: "#EC0F6C",
    axisLabelFill: "White",
    labelPlacement: ELabelPlacement.BottomRight, labelValue: "Values above this line are red",
    showLabel: true}));
};

drawBubbleChartWithPalette("scichart-root");





async function builderExample(divElementId) {
  // Demonstrates how to create a bubble with SciChart.js using the Builder API
  const {
    chartBuilder,
    ESeriesType,
    EPointMarkerType,
    EThemeProviderType,
    EBaseType,
    EPaletteProviderType
  } = SciChart;

  // or, for npm, import { chartBuilder, ... } from "scichart"

  const xValues = [];
  const yValues = [];
  const sizes = [];
  for(let i = 0; i < 30; i++) {
    xValues.push(i);
    yValues.push(0.2 * Math.sin(i*0.2) - Math.cos(i * 0.04));
    sizes.push(Math.sin(i) * 60 + 3);
  }

  // #region ExampleC
  // Register the custom BubblePaletteProvider with the chartBuilder
  chartBuilder.registerType(EBaseType.PaletteProvider, "BubblePaletteProvider",
      (options) => new BubblePaletteProvider(options.fill, options.rule));

  const { wasmContext, sciChartSurface } = await chartBuilder.build2DChart(divElementId, {
    surface: { theme: { type: EThemeProviderType.Dark } },
    series: [
      {
        type: ESeriesType.BubbleSeries,
        xyzData: {
          xValues,
          yValues,
          zValues: sizes
        },
        options: {
          pointMarker: {
            type: EPointMarkerType.Ellipse,
            options: {
              // choose a suitably large size for pointmarker. This will  be scaled per-point
              width: 64,
              height: 64,
              strokeThickness: 0,
              fill: "#4682b477"
            }
          },
          // Now you can instantiate using parameters below
          paletteProvider: {
            type: EPaletteProviderType.Custom,
            customType: "BubblePaletteProvider",
            options: {
              fill: "Red",
              rule: (yValue) => yValue >= -0.8,
            }
          }
          // Note: Assigning an instance is also valid, e.g.
          // paletteProvider: new BubblePaletteProvider("Green", "Red", yValue => yValue >= 4.0)
        }
      }
    ]
  });
  // #endregion
};



// Uncomment this to use the builder example
  //builderExample("scichart-root");

  

 

See Also