javascriptc#blazor.net-8.0scichart

SciChart's Waterfall chart with .NET Blazor wrapper


I'm trying to add this beautiful Waterfall chart SciChart has with this wrapper: https://github.com/NRTDP/SciChartBlazor But it looks like there is a problem with rendering 2d surfaces.

I've created a Chart.razor on Client side using new Blazor Web App with following code:

@page "/chart"
@using SciChartBlazor
@using SciChartBlazor.Axes
@using SciChartBlazor.DataSeries
@using SciChartBlazor.Modifiers
@using SciChartBlazor.RenderableSeries
@using SciChartBlazor.Services
@rendermode InteractiveAuto
@inject IJSRuntime JsRuntime 

<div id="@Id" @ref="_chart" style="height:600px" />
<button @onclick=Load>Load</button>
@code
{
    private string Id { get; set; } = "C" + Guid.NewGuid().ToString();

    private protected ElementReference _chart;

    SciChartBuilder _chartBuilder = default!;

    int _seriesCount = 10;

    private async void Load()
    {

        for (int i = 0; i < _seriesCount; i++)
        {
            var XAxis = new NumericAxis()
                {
                    Id = $"X{i}",
                    MaxAutoTicks = 5,
                    DrawMajorGridLines = false,
                    GrowBy = new SciChartNumberRange(0, 0.2),
                    VisibleRange = new SciChartNumberRange(-1000.0, 1000.0),
                    VisibleRangeLimit = new SciChartNumberRange(-1000.0, 1000.0),
                    IsVisible = (i == 0),
                    //OverrideOffset = 0
                };

            await _chartBuilder.AddAxis(XAxis, AxisType.X);
            var YAxis = new NumericAxis()
                {
                    Id = $"Y{i}",
                    MaxAutoTicks = 5,
                    DrawMajorGridLines = false,
                    VisibleRange = new SciChartNumberRange(-100.0, 100.0),
                    VisibleRangeLimit = new SciChartNumberRange(-1000.0, 1000.0),
                    IsVisible = (i == 0),
                    //OverrideOffset = 0
                };

            await _chartBuilder.AddAxis(YAxis, AxisType.Y);

            double[] x = new double[10];
            double[] y = new double[10];


            for (int j = 0; j < 10; j++)
            {
                x[j] = (double)j;
                y[j] = Math.Sin(j) * 100 + i;
            }

            var ser = new XyDataSeries<double, double>(x, y) { DataSeriesName = $"N{i}" };

            var fastLineRenderableSeries = new SciChartBlazor.RenderableSeries.FastLineRenderableSeries<double, double>(ser)
                { Id = $"S{i}", XAxisId = $"X{i}", YAxisId = $"Y{i}", StrokeThickness = 1, Stroke = "#64BAE4" };

            await _chartBuilder.AddSeries(fastLineRenderableSeries);
        }

    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            //Create the chart
            _chartBuilder = new SciChartBuilder(_chart, JsRuntime, new SciChartBlazorService(JsRuntime, new SciChartOptions()));
            await _chartBuilder.CreateChart();
        }
    }
} 

With _seriesCount equals 1 it builds a simple chart, but adding more series returns an error in a line:

 this.nativeArgs.StartIndex = rp.indexesRange.min

Full trace:

Error from chart in div Ced51579e-26cc-4536-96e2-49f46254f9db: TypeError: Cannot read properties of undefined (reading 'min')
    at ExtremeResamplerHelper.resetAndFillBasicNativeArgs (ExtremeResamplerHelper.js:178:54)
    at ExtremeResamplerHelper.needsResampling (ExtremeResamplerHelper.js:50:18)
    at BaseRenderableSeries.needsResampling (BaseRenderableSeries.js:935:37)
    at SciChartRenderer.resampleSeries (SciChartRenderer.js:65:17)
    at SciChartRenderer.prepareSeriesRenderData (SciChartRenderer.js:328:57)
    at SciChartRenderer.render (SciChartRenderer.js:144:35)
    at SciChartSurface.doDrawingLoop (SciChartSurface.js:707:35)
    at SciChartSurface.onRenderSurfaceDraw (SciChartSurface.js:1337:18)
    at RenderSurface.onRenderTimeElapsed (RenderSurface.js:37:14)
    at Object.Draw (createMaster.js:294:60)

Following this stacktrace at SciChartRenderer.resampleSeries (SciChartRenderer.js:65:17)

 var rp = new ResamplingParams_1.ResamplingParams(seriesViewRect, rs, xAxis);

where

var ResamplingParams_1 = __webpack_require__(/*! ../Numerics/Resamplers/ResamplingParams */ "./node_modules/scichart/Charting/Numerics/Resamplers/ResamplingParams.js");

it looks like rp is not created correctly but I don't understand why?

Ps I've downloaded the package from git and didn't use NuGet. Also you can find js equivalent of this here https://github.com/ABTSoftware/SciChart.JS.Examples/blob/master/Examples/src/components/Examples/FeaturedApps/ScientificCharts/InteractiveWaterfallChart/index.tsx

Also you will need to add this line in your App.razor:

<script async src="_content/SciChartBlazor/SciChart/sciChartBlazorJson.js"></script>

Solution

  • After struggling with NRTDP/SciChartBlazor, i've tried SciChart/JS with blazor - and it works fine, with easy.

    My suggesting is to not be dependant (in this case) on a NuGet that was last updated 2y-ago (as to date).

    I tried to contribute to SciChartBlazor, and after seeing the internals of it - it's not covering SciChart API and you'll need/end-up adding JS anyway to support what you need.

    So, here is how one can...

    Get SciChart/JS with blazor-server-app works.

    Pages \ _Layout.cshtml

    <head>
    ...
        
        <!-- Reference the latest version is not recommended for production! -->
        @* <script src="https://cdn.jsdelivr.net/npm/scichart/index.min.js" crossorigin="anonymous"></script> *@
        <script src="https://cdn.jsdelivr.net/npm/scichart@3.3.577/index.min.js" crossorigin="anonymous"></script>
    
        <script src="~/MySciChartGraphsApi.js"></script>
    
        <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
    </head>
    

    Pages\MyPage.razor

    <div class="GTGraph" id="scichart-root" style="visibility: @graphVisibility"></div>
    

    wwwroot\MySciChartGraphsApi.js

    function helloSciChart() {
        return "SciChart-world";
    }
    
    
    // Create a SciChartSurface in the div 'scichart-root'
    async function initSciChart() {
        // based on: 
        // * https://www.scichart.com/getting-started/scichart-javascript/
        // ** https://codepen.io/scichart/pen/eYPXazY
    
        const {
            SciChartSurface,
            NumericAxis,
            FastLineRenderableSeries,
            XyDataSeries,
            EllipsePointMarker,
            SweepAnimation,
            SciChartJsNavyTheme,
            NumberRange,
            MouseWheelZoomModifier,
            ZoomPanModifier,
            ZoomExtentsModifier
        } = SciChart;
    
        // Tell SciChart where to get webassembly files from.
        SciChartSurface.useWasmFromCDN();
    
        // Initialize SciChartSurface. Don't forget to await!
        const { sciChartSurface, wasmContext } = await SciChartSurface.create("scichart-root", {
            theme: new SciChartJsNavyTheme(),
            title: "SciChart.js First Chart",
            titleStyle: { fontSize: 22 }
        });
    
        // Create an XAxis and YAxis with growBy padding
        const growBy = new NumberRange(0.1, 0.1);
        sciChartSurface.xAxes.add(new NumericAxis(wasmContext, { axisTitle: "X Axis", growBy }));
        sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { axisTitle: "Y Axis", growBy }));
    
        // Create a line series with some initial data
        sciChartSurface.renderableSeries.add(new FastLineRenderableSeries(wasmContext, {
            stroke: "steelblue",
            strokeThickness: 3,
            dataSeries: new XyDataSeries(wasmContext, {
                xValues: [0,1,2,3,4,5,6,7,8,9],
                yValues: [0, 0.0998, 0.1986, 0.2955, 0.3894, 0.4794, 0.5646, 0.6442, 0.7173, 0.7833]
            }),
            pointMarker: new EllipsePointMarker(wasmContext, { width: 11, height: 11, fill: "#fff" }),
            animation: new SweepAnimation({ duration: 300, fadeEffect: true })
        }));
      
        // Add some interaction modifiers to show zooming and panning
        sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier(), new ZoomPanModifier(), new ZoomExtentsModifier());
    
        return "done";
    };
    

    CSS-file

    .MyGraph { height: 400px; }
    

    Your-Page.razor / HTML

    <div id="scichart-root" class="MyGraph"></div>
    

    Your-Page.razor.cs

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            try
            {
                // string result2 = await JSRuntime.InvokeAsync<string>("helloSciChart");  // checking JS works
                string result3 = await JSRuntime.InvokeAsync<string>("initSciChart");
    
            }
            catch (Exception exception)
            {
                Logger.LogError("exception: {exception}", exception);
            }
        }
    
        await base.OnAfterRenderAsync(firstRender);
    }
    

    Expected result.

    enter image description here

    BONUS for using SciChart/JS

    HTH.