SciChart.js JavaScript 2D Charts API > 2D Chart Types > Data PointMetadata API > DataSeries PointMetaData API
DataSeries PointMetaData API

The PointMetadata API in SciChart.js allows you to:

  • Tag any X,Y point in a DataSeries with a custom JavaScript object
  • It can be used with the DataPoint Selection Modifier to enable per-point selection
  • It can be used with the PaletteProvider API to provide custom colouring of data-points in a series.
  • It can be used with tooltips such as CursorModifier and RolloverModifier to display extra data or info inside a tooltip
  • Finally, it can be used in the result of any Hit-Test operation where X,Y,Metadata can be queried on click

Adding Metadata to Charts

Metadata is optional and can be set when a dataseries is first created, or whenever data is added or updated. Metadata is just a JavaScript object and can contain any properties, objects, even functions.

See the example below for how to create metadata when constructing an XyDataSeries and how to consume it in a RolloverModifier.

// Demonstrates how to add PointMetadata to a DataSeries and consume it in SciChart.js
const {
  SciChartSurface,
  NumericAxis,
  FastLineRenderableSeries,
  XyDataSeries,
  SciChartJsNavyTheme,
  EllipsePointMarker,
  NumberRange,
  RolloverModifier
} = SciChart;

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

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

const growBy = new NumberRange(0.1, 0.1);
sciChartSurface.xAxes.add(new NumericAxis(wasmContext, { growBy }));
sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { growBy }));

// Create metadata with initial values. Metadata can be any JS object
const dataSeries = new XyDataSeries(wasmContext, {
  xValues: [1, 2, 3, 4, 5],
  yValues: [4.3, 5.3, 6, 6.3, 6.4],
  metadata: [
    { stringValue: "Here's", customValue: 7 },
    undefined, // nothing at this index
    { stringValue: "Some" },
    { }, // empty object at this index
    { stringValue: "Metadata", customValue: 99},
  ]
});

// Add a line series with the metadata
sciChartSurface.renderableSeries.add(new FastLineRenderableSeries(wasmContext, {
  dataSeries,
  pointMarker: new EllipsePointMarker(wasmContext, { width: 11, height: 11, fill: "#364BA0", stroke: "#50C7E0", strokeThickness: 2 }),
}));

// Add a RolloverModifier configured to output X,Y,Metadata.stringValue and customValue
sciChartSurface.chartModifiers.add(new RolloverModifier( {
  snapToDataPoint: true,
  tooltipDataTemplate: (seriesInfo) => [
    `X: ${seriesInfo.formattedXValue}`,
    `Y: ${seriesInfo.formattedYValue}`,
    `Metadata.stringValue: ${seriesInfo.pointMetadata?.stringValue ?? 'null'}`,
    `Metadata.customValue: ${seriesInfo.pointMetadata?.customValue ?? 'null'}`
  ]
}));
// Demonstrates how to add PointMetadata to a DataSeries and consume it in SciChart.js with the BuilderAPI
const {
  chartBuilder,
  ESeriesType,
  EThemeProviderType,
  EChart2DModifierType,
  EPointMarkerType
} = SciChart;

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

const { wasmContext, sciChartSurface } = await chartBuilder.build2DChart(divElementId, {
  surface: { theme: { type: EThemeProviderType.Dark } },
  series: [
    {
      type: ESeriesType.LineSeries,
      // Metadata is set in xyData property
      xyData: {
        xValues: [1, 2, 3, 4, 5],
        yValues: [4.3, 5.3, 6, 6.3, 6.4],
        metadata: [
          { stringValue: "Here's", customValue: 7 },
          undefined, // nothing at this index
          { stringValue: "Some" },
          { }, // empty object at this index
          { stringValue: "Metadata", customValue: 99},
        ]
      },
      options: {
        stroke: "#C52E60",
        pointMarker: {
          type: EPointMarkerType.Ellipse,
          options: {
            width: 11, height: 11, fill: "White"
          }
        }
      }
    }
  ],
  // Configure a Rollovermodifier to display metadata
  modifiers: [{
    type: EChart2DModifierType.Rollover,
    options: {
      snapToDataPoint: true,
      tooltipDataTemplate: (seriesInfo) => [
        `X: ${seriesInfo.formattedXValue}`,
        `Y: ${seriesInfo.formattedYValue}`,
        `Metadata.stringValue: ${seriesInfo.pointMetadata?.stringValue ?? 'null'}`,
        `Metadata.customValue: ${seriesInfo.pointMetadata?.customValue ?? 'null'}`
      ]
    }
  }]
});

This results in the following output

<div id="scichart-root" ></div>
  
body { margin: 0; }
#scichart-root { width: 100%; height: 100vh; }
  
async function addingMetadata(divElementId) {
  // #region ExampleA
  // Demonstrates how to add PointMetadata to a DataSeries and consume it in SciChart.js
  const {
    SciChartSurface,
    NumericAxis,
    FastLineRenderableSeries,
    XyDataSeries,
    SciChartJsNavyTheme,
    EllipsePointMarker,
    NumberRange,
    RolloverModifier
  } = SciChart;

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

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

  const growBy = new NumberRange(0.1, 0.1);
  sciChartSurface.xAxes.add(new NumericAxis(wasmContext, { growBy }));
  sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { growBy }));

  // Create metadata with initial values. Metadata can be any JS object
  const dataSeries = new XyDataSeries(wasmContext, {
    xValues: [1, 2, 3, 4, 5],
    yValues: [4.3, 5.3, 6, 6.3, 6.4],
    metadata: [
      { stringValue: "Here's", customValue: 7 },
      undefined, // nothing at this index
      { stringValue: "Some" },
      { }, // empty object at this index
      { stringValue: "Metadata", customValue: 99},
    ]
  });

  // Add a line series with the metadata
  sciChartSurface.renderableSeries.add(new FastLineRenderableSeries(wasmContext, {
    dataSeries,
    pointMarker: new EllipsePointMarker(wasmContext, { width: 11, height: 11, fill: "#364BA0", stroke: "#50C7E0", strokeThickness: 2 }),
  }));

  // Add a RolloverModifier configured to output X,Y,Metadata.stringValue and customValue
  sciChartSurface.chartModifiers.add(new RolloverModifier( {
    snapToDataPoint: true,
    tooltipDataTemplate: (seriesInfo) => [
      `X: ${seriesInfo.formattedXValue}`,
      `Y: ${seriesInfo.formattedYValue}`,
      `Metadata.stringValue: ${seriesInfo.pointMetadata?.stringValue ?? 'null'}`,
      `Metadata.customValue: ${seriesInfo.pointMetadata?.customValue ?? 'null'}`
    ]
  }));
  // #endregion

  const { TextAnnotation, EHorizontalAnchorPoint, ECoordinateMode, EAnnotationLayer } = SciChart;
  const options = {
    xCoordinateMode: ECoordinateMode.Relative,
    yCoordinateMode: ECoordinateMode.Relative,
    x1: 0.5,
    y1: 0.5,
    horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
    opacity: 0.33,
    textColor: "White",
  };
  sciChartSurface.annotations.add(new TextAnnotation({
    text: "Create Metadata Example",
    fontSize: 36,
    yCoordShift: -125,
    ... options,
  }));
  sciChartSurface.annotations.add(new TextAnnotation({
    text: "Hover over the chart to see metadata",
    fontSize: 20,
    yCoordShift: -75,
    ... options,
  }));
};

addingMetadata("scichart-root");





async function builderExample(divElementId) {
  // #region ExampleB
  // Demonstrates how to add PointMetadata to a DataSeries and consume it in SciChart.js with the BuilderAPI
  const {
    chartBuilder,
    ESeriesType,
    EThemeProviderType,
    EChart2DModifierType,
    EPointMarkerType
  } = SciChart;

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

  const { wasmContext, sciChartSurface } = await chartBuilder.build2DChart(divElementId, {
    surface: { theme: { type: EThemeProviderType.Dark } },
    series: [
      {
        type: ESeriesType.LineSeries,
        // Metadata is set in xyData property
        xyData: {
          xValues: [1, 2, 3, 4, 5],
          yValues: [4.3, 5.3, 6, 6.3, 6.4],
          metadata: [
            { stringValue: "Here's", customValue: 7 },
            undefined, // nothing at this index
            { stringValue: "Some" },
            { }, // empty object at this index
            { stringValue: "Metadata", customValue: 99},
          ]
        },
        options: {
          stroke: "#C52E60",
          pointMarker: {
            type: EPointMarkerType.Ellipse,
            options: {
              width: 11, height: 11, fill: "White"
            }
          }
        }
      }
    ],
    // Configure a Rollovermodifier to display metadata
    modifiers: [{
      type: EChart2DModifierType.Rollover,
      options: {
        snapToDataPoint: true,
        tooltipDataTemplate: (seriesInfo) => [
          `X: ${seriesInfo.formattedXValue}`,
          `Y: ${seriesInfo.formattedYValue}`,
          `Metadata.stringValue: ${seriesInfo.pointMetadata?.stringValue ?? 'null'}`,
          `Metadata.customValue: ${seriesInfo.pointMetadata?.customValue ?? 'null'}`
        ]
      }
    }]
  });
  // #endregion
};



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

  

 

Note: You do not have to set metadata on every point. The structure of the metadata does not have to be the same for every point.

In TypeScript, all metadata must implement the IPointMetadata interface, ie  { isSelected: boolean }. For JavaScript, this property can be omitted.

Metadata Templates

If you just need to set the same metadata on every point, you can supply a single metadata object and it will be used as a template and be cloned onto each datapoint. For example:

// Set a single object, this will be cloned as a template for all metadata on the dataseries
const dataSeries = new XyDataSeries(wasmContext, {
  xValues: [1, 2, 3, 4, 5],
  yValues: [4.3, 5.3, 6, 6.3, 6.4],
  metadata: { stringValue: "All the same value", customValue: 7 },
});

// Update just a metadata value
// Update just a metadata value.  This will not trigger a chart redraw
dataSeries.getMetadataAt(0).stringValue = "Updated #0";
// To force a redraw, use update and pass a new metadata object
dataSeries.update(1, 5.3, { stringValue: "Updated #1 with redraw", customValue: 99 });
// Or, to trigger a redraw, call invalidateElement() on the parent SciChartSurface
sciChartSurface.invalidateElement();
const { wasmContext, sciChartSurface } = await chartBuilder.build2DChart(divElementId, {
  surface: { theme: { type: EThemeProviderType.Dark } },
  series: [
    {
      type: ESeriesType.LineSeries,
      // Metadata is set in xyData property
      xyData: {
        xValues: [1, 2, 3, 4, 5],
        yValues: [4.3, 5.3, 6, 6.3, 6.4],
        metadata: { stringValue: "All the same value", customValue: 7 },
      },
      // ...
<div id="scichart-root" ></div>
  
body { margin: 0; }
#scichart-root { width: 100%; height: 100vh; }
  
async function metadataTemplates(divElementId) {
  // Demonstrates how to add PointMetadata to a DataSeries and consume it in SciChart.js
  const {
    SciChartSurface,
    NumericAxis,
    FastLineRenderableSeries,
    XyDataSeries,
    SciChartJsNavyTheme,
    EllipsePointMarker,
    NumberRange,
    RolloverModifier
  } = SciChart;

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

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

  const growBy = new NumberRange(0.1, 0.1);
  sciChartSurface.xAxes.add(new NumericAxis(wasmContext, { growBy }));
  sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { growBy }));

  // #region ExampleA
  // Set a single object, this will be cloned as a template for all metadata on the dataseries
  const dataSeries = new XyDataSeries(wasmContext, {
    xValues: [1, 2, 3, 4, 5],
    yValues: [4.3, 5.3, 6, 6.3, 6.4],
    metadata: { stringValue: "All the same value", customValue: 7 },
  });

  // Update just a metadata value
  // Update just a metadata value.  This will not trigger a chart redraw
  dataSeries.getMetadataAt(0).stringValue = "Updated #0";
  // To force a redraw, use update and pass a new metadata object
  dataSeries.update(1, 5.3, { stringValue: "Updated #1 with redraw", customValue: 99 });
  // Or, to trigger a redraw, call invalidateElement() on the parent SciChartSurface
  sciChartSurface.invalidateElement();
  // #endregion

  // Add a line series with the metadata
  sciChartSurface.renderableSeries.add(new FastLineRenderableSeries(wasmContext, {
    dataSeries,
    pointMarker: new EllipsePointMarker(wasmContext, { width: 11, height: 11, fill: "White" }),
  }));
  // Add a RolloverModifier configured to output X,Y,Metadata.stringValue and customValue
  sciChartSurface.chartModifiers.add(new RolloverModifier( {
    snapToDataPoint: true,
    tooltipDataTemplate: (seriesInfo) => [
      `X: ${seriesInfo.formattedXValue}`,
      `Y: ${seriesInfo.formattedYValue}`,
      `Metadata.stringValue: ${seriesInfo.pointMetadata?.stringValue ?? 'null'}`,
      `Metadata.customValue: ${seriesInfo.pointMetadata?.customValue ?? 'null'}`
    ]
  }));
  // #endregion

  const { TextAnnotation, EHorizontalAnchorPoint, ECoordinateMode, EAnnotationLayer } = SciChart;
  const options = {
    xCoordinateMode: ECoordinateMode.Relative,
    yCoordinateMode: ECoordinateMode.Relative,
    x1: 0.5,
    y1: 0.5,
    horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
    opacity: 0.33,
    textColor: "White",
  };
  sciChartSurface.annotations.add(new TextAnnotation({
    text: "Metadata Templates Example",
    fontSize: 36,
    yCoordShift: -125,
    ... options,
  }));
  sciChartSurface.annotations.add(new TextAnnotation({
    text: "Hover over the chart to see metadata",
    fontSize: 20,
    yCoordShift: -75,
    ... options,
  }));
};

metadataTemplates("scichart-root");





async function builderExample(divElementId) {
  // Demonstrates how to add PointMetadata to a DataSeries and consume it in SciChart.js with the BuilderAPI
  const {
    chartBuilder,
    ESeriesType,
    EThemeProviderType,
    EChart2DModifierType,
    EPointMarkerType
  } = SciChart;

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

  // #region ExampleB
  const { wasmContext, sciChartSurface } = await chartBuilder.build2DChart(divElementId, {
    surface: { theme: { type: EThemeProviderType.Dark } },
    series: [
      {
        type: ESeriesType.LineSeries,
        // Metadata is set in xyData property
        xyData: {
          xValues: [1, 2, 3, 4, 5],
          yValues: [4.3, 5.3, 6, 6.3, 6.4],
          metadata: { stringValue: "All the same value", customValue: 7 },
        },
        // ...
        // #endregion
        options: {
          stroke: "#C52E60",
          pointMarker: {
            type: EPointMarkerType.Ellipse,
            options: {
              width: 11, height: 11, fill: "White"
            }
          }
        }
      }
    ],
    // Configure a Rollovermodifier to display metadata
    modifiers: [{
      type: EChart2DModifierType.Rollover,
      options: {
        snapToDataPoint: true,
        tooltipDataTemplate: (seriesInfo) => [
          `X: ${seriesInfo.formattedXValue}`,
          `Y: ${seriesInfo.formattedYValue}`,
          `Metadata.stringValue: ${seriesInfo.pointMetadata?.stringValue ?? 'null'}`,
          `Metadata.customValue: ${seriesInfo.pointMetadata?.customValue ?? 'null'}`
        ]
      }
    }]
  });

};



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

  

 

Metadata Generators

If you want to set complex metadata using the Builder Api you have the option to take control of how the metadata is deserialized and serialized by passing a MetadataGenerator. This is a class that should accept raw data in its constructor and have a getMetadata method that returns a metadata array.

// Create a metadata class. Confirms to interface I1DMetadataGenerator
class ExampleMetadataGenerator  {
  // Accept and store the raw data in the constructor
  constructor (stringArray) {
    console.log(`${stringArray}`);
    this.stringValues = stringArray
    this.type = "ExampleMetadataGenerator";
  };
  // This is called by SciChart to get the metadata to set when the dataSeries is created
  getMetadata = () => this.stringValues.map(s => ({ stringValue: s }));
  // Unused for this example. Used to create a clone of metadata template for each datapoint
  getSingleMetadata = () => ({ stringValue: "" });
  // Required for serialization and builder API
  toJSON = () => ({ type: this.type, data: this.stringValues });
}

Before this class can be used with the builder api it must be registered. Then, it can be used like this:

// call chartBuilder.registerType to register a new custom type
chartBuilder.registerType(EBaseType.MetadataGenerator, "ExampleMetadataGenerator", (data) => new ExampleMetadataGenerator(data));

// Assign a Metadata generator instance to create metadata dynamically
const dataSeries = new XyDataSeries(wasmContext, {
  xValues: [1, 2, 3, 4, 5],
  yValues: [4.3, 5.3, 6, 6.3, 6.4],
  metadata: { type: "ExampleMetadataGenerator", data: ["Here's", "Some", "Metadata", "From", "Generator"] },
});
// call chartBuilder.registerType to register a new custom type
chartBuilder.registerType(EBaseType.MetadataGenerator, "ExampleMetadataGenerator", (data) => new ExampleMetadataGenerator(data));

const { wasmContext, sciChartSurface } = await chartBuilder.build2DChart(divElementId, {
  surface: { theme: { type: EThemeProviderType.Dark } },
  series: [
    {
      type: ESeriesType.LineSeries,
      // Metadata is set in xyData property
      xyData: {
        xValues: [1, 2, 3, 4, 5],
        yValues: [4.3, 5.3, 6, 6.3, 6.4],
        metadata: { type: "ExampleMetadataGenerator", data: ["Here's", "Some", "Metadata", "From", "Generator"] },
      },
      // ...
<div id="scichart-root" ></div>
  
body { margin: 0; }
#scichart-root { width: 100%; height: 100vh; }
  
// #region ExampleA
// Create a metadata class. Confirms to interface I1DMetadataGenerator
class ExampleMetadataGenerator  {
  // Accept and store the raw data in the constructor
  constructor (stringArray) {
    console.log(`${stringArray}`);
    this.stringValues = stringArray
    this.type = "ExampleMetadataGenerator";
  };
  // This is called by SciChart to get the metadata to set when the dataSeries is created
  getMetadata = () => this.stringValues.map(s => ({ stringValue: s }));
  // Unused for this example. Used to create a clone of metadata template for each datapoint
  getSingleMetadata = () => ({ stringValue: "" });
  // Required for serialization and builder API
  toJSON = () => ({ type: this.type, data: this.stringValues });
}
// #endregion

async function metadataGenerators(divElementId) {
  // Demonstrates how to add PointMetadata to a DataSeries and consume it in SciChart.js
  const {
    SciChartSurface,
    NumericAxis,
    FastLineRenderableSeries,
    XyDataSeries,
    SciChartJsNavyTheme,
    EllipsePointMarker,
    NumberRange,
    RolloverModifier,
    EBaseType,
    chartBuilder
  } = SciChart;

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

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

  const growBy = new NumberRange(0.1, 0.1);
  sciChartSurface.xAxes.add(new NumericAxis(wasmContext, { growBy }));
  sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { growBy }));

  // #region ExampleB
  // call chartBuilder.registerType to register a new custom type
  chartBuilder.registerType(EBaseType.MetadataGenerator, "ExampleMetadataGenerator", (data) => new ExampleMetadataGenerator(data));

  // Assign a Metadata generator instance to create metadata dynamically
  const dataSeries = new XyDataSeries(wasmContext, {
    xValues: [1, 2, 3, 4, 5],
    yValues: [4.3, 5.3, 6, 6.3, 6.4],
    metadata: { type: "ExampleMetadataGenerator", data: ["Here's", "Some", "Metadata", "From", "Generator"] },
  });
  // #endregion

  // Add a line series with the metadata
  sciChartSurface.renderableSeries.add(new FastLineRenderableSeries(wasmContext, {
    dataSeries,
    pointMarker: new EllipsePointMarker(wasmContext, { width: 11, height: 11, fill: "White" }),
  }));
  // Add a RolloverModifier configured to output X,Y,Metadata.stringValue and customValue
  sciChartSurface.chartModifiers.add(new RolloverModifier( {
    snapToDataPoint: true,
    tooltipDataTemplate: (seriesInfo) => [
      `X: ${seriesInfo.formattedXValue}`,
      `Y: ${seriesInfo.formattedYValue}`,
      `Metadata.stringValue: ${seriesInfo.pointMetadata?.stringValue ?? 'null'}`
    ]
  }));
  // #endregion

  const { TextAnnotation, EHorizontalAnchorPoint, ECoordinateMode, EAnnotationLayer } = SciChart;
  const options = {
    xCoordinateMode: ECoordinateMode.Relative,
    yCoordinateMode: ECoordinateMode.Relative,
    x1: 0.5,
    y1: 0.5,
    horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
    opacity: 0.33,
    textColor: "White",
  };
  sciChartSurface.annotations.add(new TextAnnotation({
    text: "Metadata Generators Example",
    fontSize: 36,
    yCoordShift: -125,
    ... options,
  }));
  sciChartSurface.annotations.add(new TextAnnotation({
    text: "Hover over the chart to see metadata",
    fontSize: 20,
    yCoordShift: -75,
    ... options,
  }));
};

metadataGenerators("scichart-root");





async function builderExample(divElementId) {
  // Demonstrates how to add PointMetadata to a DataSeries and consume it in SciChart.js with the BuilderAPI
  const {
    chartBuilder,
    ESeriesType,
    EThemeProviderType,
    EChart2DModifierType,
    EPointMarkerType,
    EBaseType
  } = SciChart;

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

  // #region ExampleC
  // call chartBuilder.registerType to register a new custom type
  chartBuilder.registerType(EBaseType.MetadataGenerator, "ExampleMetadataGenerator", (data) => new ExampleMetadataGenerator(data));

  const { wasmContext, sciChartSurface } = await chartBuilder.build2DChart(divElementId, {
    surface: { theme: { type: EThemeProviderType.Dark } },
    series: [
      {
        type: ESeriesType.LineSeries,
        // Metadata is set in xyData property
        xyData: {
          xValues: [1, 2, 3, 4, 5],
          yValues: [4.3, 5.3, 6, 6.3, 6.4],
          metadata: { type: "ExampleMetadataGenerator", data: ["Here's", "Some", "Metadata", "From", "Generator"] },
        },
        // ...
        // #endregion
        options: {
          stroke: "#C52E60",
          pointMarker: {
            type: EPointMarkerType.Ellipse,
            options: {
              width: 11, height: 11, fill: "White"
            }
          }
        }
      }
    ],

    // Configure a Rollovermodifier to display metadata
    modifiers: [{
      type: EChart2DModifierType.Rollover,
      options: {
        snapToDataPoint: true,
        tooltipDataTemplate: (seriesInfo) => [
          `X: ${seriesInfo.formattedXValue}`,
          `Y: ${seriesInfo.formattedYValue}`,
          `Metadata.stringValue: ${seriesInfo.pointMetadata?.stringValue ?? 'null'}`
        ]
      }
    }]
  });
};



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

  
Note: for more info about the Builder API, please see the section in our documentation here.