Pre loader

Override Individual PointMarker Shapes Within a Single Series

Welcome to the SciChart Forums!

  • Please read our Question Asking Guidelines for how to format a good question
  • Some reputation is required to post answers. Get up-voted to avoid the spam filter!
  • We welcome community answers and upvotes. Every Q&A improves SciChart for everyone

WPF Forums | JavaScript Forums | Android Forums | iOS Forums

1
0

Is there a way to override the shape of each individual PointMarker within the same series based on the metadata? I can override the color of individual points in the DefaultPaletteProvider, but I haven’t found a solution for the shape.

Version
3.3.586
  • You must to post comments
0
0

Hi there

Yes there is, post SciChart.js v3.4 where we now have a new Render Data Transforms API.

This new API allows you to create a single series with multiple styles, for example you can switch pointmarker type mid-series, switch dash style or stroke thickness or opacity mid-series or have different gradient fills in a column series mid-series.

Take a look a the Multi-Style Series demo for a complex example.

javascript chart with multiple styles in same series

Below I’ll include an excerpt from the Render Data Transforms API documentation.

RenderDataTransforms allow you to transform your data immediately before it is drawn.

This allows you to change visual output performing transforms on chart series, while keeping your data unchanged – meaning tooltips, cursors and more are unchanged by this type of transform.

Some examples of uses of RenderDataTransforms are:

  • Interpolating the data. SciChart uses the RenderDataTransforms API internally to draw the spline series
  • Switching Styles on a series, for example rendering data on the same series with different pointmarkers or line styles.
  • Splitting Line Segments, adding points into the data to be able to draw a single line segment in multiple colors
  • Adding Gaps to series by manipulating NaN values

In the RenderDataTransforms documentation page above we have a worked example of how to render a single series with both triangle and square point markers.

This works by creating a class SplitBySelectedDataTransform which inherits XyyBaseRenderDataTransform that allows you to have two sets of yValues for rendering: yValues and y1Values.

These are filled with alternate X,Y values or NAN depending on which style we want to show.

e.g.

class SplitBySelectedDataTransform extends XyyBaseRenderDataTransform {
  protected runTransformInternal(renderPassData: RenderPassData): IPointSeries {
    /// ...
    for (let i = iStart; i <= iEnd; i++) {
      // If data has been resampled, we need the original index in order to get the correct metadata
      const index = resampled ? oldI.get(i) : i;
      const md = ds.getMetadataAt(index);
      xValues.push_back(oldX.get(i));
      indexes.push_back(index);
      // Push the y value to the desired target vector
      if (md.isSelected) {
        // display style 2 using y1Values. 
        // yValues is NAN (hidden for this style)
        yValues.push_back(Number.NaN);
        y1Values.push_back(oldY.get(i));
      } else {
        // display style 1 using y2Values. 
        // y2Values is NAN (hidden for this style)
        yValues.push_back(oldY.get(i));
        y1Values.push_back(Number.NaN);
      }
    }
    // Return the transformed pointSeries.
    return this.pointSeries;
  }
}

Later the render transform is applied to the series by setting up a second drawing provider which consumes the y1Values from our SplitBySelectedDataTransform

const renderableSeries = new XyScatterRenderableSeries(wasmContext, {
  dataSeries: new XyDataSeries(wasmContext, { ... }),
  pointMarker: new TrianglePointMarker(wasmContext, {
    width: 10,
    height: 10,
    stroke: "green",
    fill: "green",
  }),
});

// Create a second PointMarkerDrawingProvider with a ySelector so that it uses y1Values
const selectedPointDrawingProvider = new PointMarkerDrawingProvider(
  wasmContext,
  renderableSeries,
  (ps) => (ps as IXyyPointSeries).y1Values
);
// Create a different pointMarker
const squarePM = new SquarePointMarker(wasmContext, { width: 10, height: 10, stroke: "red", fill: "red" });

// Tell the new drawingProvider to use the new pointmarker instead of the one from the series.
selectedPointDrawingProvider.getProperties = () => ({
  pointMarker: squarePM as IPointMarker,
});
// Add the new drawingProvider to the series
renderableSeries.drawingProviders.push(selectedPointDrawingProvider);
// Create the transform and add it to the series.  Pass the drawingProviders array as this transform applies to all of them
renderableSeries.renderDataTransform = new SplitBySelectedDataTransform(
  renderableSeries,
  wasmContext,
  renderableSeries.drawingProviders
);
sciChartSurface.renderableSeries.add(renderableSeries);

Finally the Render Data Transforms API documentation page has a few worked examples and codepens you can work through.

Best regards,
Andrew

  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.