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>
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...
<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>
<div class="GTGraph" id="scichart-root" style="visibility: @graphVisibility"></div>
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";
};
.MyGraph { height: 400px; }
<div id="scichart-root" class="MyGraph"></div>
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);
}
HTH.