Blazorise SVG Chart Streaming

Append live data and keep the chart viewport moving.

SVG chart streaming is configured with SvgChartStreamingOptions. Set Duration to a time window for rolling retention, or leave Duration as null for infinite retention.

Examples

Append values

Append values through the chart reference. A timer can call the same method in a live application.
1 series, 13 categories.Live latencyRight-to-left viewport with infinite retention00.20.40.60.81

Append a value or hover over a point.

@using System.Threading
@implements IAsyncDisposable

<Button Color="Color.Primary" Outline Clicked="@AppendValue">
    Append value
</Button>

<SvgLineChart @ref="chart"
              TItem="object"
              Data="@data"
              Options="@options"
              Streaming="@streaming"
              Hovered="@OnPointHovered">
    <SvgChartTitle Title='@("Live latency")' Subtitle='@("Right-to-left viewport with infinite retention")' />
    <SvgChartTooltip Enabled />
    <SvgChartValueAxis BeginAtZero TickCount="6" />
</SvgLineChart>

<Paragraph Margin="Margin.Is2.FromTop.Is0.FromBottom">@lastEvent</Paragraph>
@code {
    private static readonly TimeSpan StreamingInterval = TimeSpan.FromSeconds( 1 );

    private SvgLineChart<object> chart;

    private readonly Random random = new();

    private double currentLatency = 45;

    private string lastEvent = "Append a value or hover over a point.";

    private CancellationTokenSource streamingCancellationTokenSource;

    private Task streamingTask;

    private readonly SvgChartOptions options = new()
    {
        Height = 360,
        Legend = new() { Visible = false },
        XAxis = new()
        {
            GridLines = new() { Visible = true },
            Labels = new()
            {
                Step = 2,
                Offset = 30,
            },
        },
    };

    private readonly SvgChartStreamingOptions streaming = new()
    {
        Enabled = true,
        VisibleDataPoints = 12,
        Duration = null,
        Reverse = false,
        Animation = new()
        {
            Duration = StreamingInterval,
        },
        RefreshInterval = TimeSpan.FromMilliseconds( 500 ),
    };

    private readonly SvgChartData<double?> data = new()
    {
        Series =
        [
            new()
            {
                Name = "Latency",
                Color = Color.Primary,
            },
        ],
    };

    protected override Task OnAfterRenderAsync( bool firstRender )
    {
        if ( firstRender )
        {
            streamingCancellationTokenSource = new();
            streamingTask = RunStreamingAsync( streamingCancellationTokenSource.Token );
        }

        return Task.CompletedTask;
    }

    private async Task RunStreamingAsync( CancellationToken cancellationToken )
    {
        try
        {
            using PeriodicTimer timer = new( StreamingInterval );

            while ( await timer.WaitForNextTickAsync( cancellationToken ) )
            {
                await InvokeAsync( AppendValue );
            }
        }
        catch ( OperationCanceledException )
        {
        }
    }

    private async Task AppendValue()
    {
        string label = DateTime.Now.ToString( "HH:mm:ss" );
        currentLatency = Math.Clamp( currentLatency + random.Next( -16, 17 ), 25, 80 );

        if ( chart is not null )
            await chart.AppendValue( "Latency", label, currentLatency );
    }

    private Task OnPointHovered( SvgChartPointEventArgs eventArgs )
    {
        lastEvent = $"Hovered {eventArgs.SeriesName} / {eventArgs.Category}: {eventArgs.Value}";

        return Task.CompletedTask;
    }

    public async ValueTask DisposeAsync()
    {
        if ( streamingCancellationTokenSource is not null )
        {
            await streamingCancellationTokenSource.CancelAsync();
            streamingCancellationTokenSource.Dispose();
        }

        if ( streamingTask is not null )
            await streamingTask;
    }
}

Rolling window

Use Duration to retain only recent timestamped samples.
1 series, 11 categories.Rolling throughputRetains the last 20 seconds of samples00.20.40.60.81
@using System.Threading
@implements IAsyncDisposable

<Button Color="Color.Primary" Outline Clicked="@AppendValue">
    Append sample
</Button>

<SvgAreaChart @ref="chart"
              TItem="object"
              Data="@data"
              Options="@options">
    <SvgChartTitle Title='@("Rolling throughput")' Subtitle='@("Retains the last 20 seconds of samples")' />
    <SvgChartTooltip Enabled />
    <SvgChartStreaming Enabled
                       VisibleDataPoints="10"
                       Duration="@TimeSpan.FromSeconds( 20 )"
                       Animation="@streamingAnimation" />
    <SvgChartTimeAxis Format="HH:mm:ss" />
    <SvgChartValueAxis BeginAtZero TickCount="6" />
</SvgAreaChart>
@code {
    private static readonly TimeSpan StreamingInterval = TimeSpan.FromSeconds( 1 );

    private readonly Random random = new( 24 );

    private SvgAreaChart<object> chart;

    private double currentThroughput = 64;

    private CancellationTokenSource streamingCancellationTokenSource;

    private Task streamingTask;

    private readonly SvgChartOptions options = new()
    {
        Height = 360,
        Legend = new() { Visible = false },
        XAxis = new()
        {
            GridLines = new() { Visible = true },
            Labels = new() { Step = 2, Offset = 30 },
        },
    };

    private readonly SvgChartStreamingAnimationOptions streamingAnimation = new()
    {
        Duration = StreamingInterval,
    };

    private readonly SvgChartData<double?> data = new()
    {
        Series =
        [
            new()
            {
                Name = "Throughput",
                Color = Color.Success,
            },
        ],
    };

    protected override Task OnAfterRenderAsync( bool firstRender )
    {
        if ( firstRender )
        {
            streamingCancellationTokenSource = new();
            streamingTask = RunStreamingAsync( streamingCancellationTokenSource.Token );
        }

        return Task.CompletedTask;
    }

    private async Task RunStreamingAsync( CancellationToken cancellationToken )
    {
        try
        {
            using PeriodicTimer timer = new( StreamingInterval );

            while ( await timer.WaitForNextTickAsync( cancellationToken ) )
            {
                await InvokeAsync( AppendValue );
            }
        }
        catch ( OperationCanceledException )
        {
        }
    }

    private async Task AppendValue()
    {
        currentThroughput = Math.Clamp( currentThroughput + random.Next( -10, 11 ), 35, 95 );

        if ( chart is not null )
            await chart.AppendValue( "Throughput", DateTimeOffset.Now, currentThroughput );
    }

    public async ValueTask DisposeAsync()
    {
        if ( streamingCancellationTokenSource is not null )
        {
            await streamingCancellationTokenSource.CancelAsync();
            streamingCancellationTokenSource.Dispose();
        }

        if ( streamingTask is not null )
            await streamingTask;
    }
}

API

Parameters

SvgChart

Parameter Description TypeDefault
AccessibilityDescription

Specifies the optional SVG description element used by assistive technologies.

string
AccessibilityTitle

Specifies the optional SVG title element used by assistive technologies.

string
Animation

Specifies chart animation options.

SvgChartAnimationOptionsnull
AriaLabel

Specifies the accessible label for the root SVG element.

string
ChildContent

Specifies the content to render inside the chart, including declarative axes, series, and options.

RenderFragmentnull
Data

Specifies explicit chart data used by imperative and model-based chart definitions.

SvgChartData<double?>null
Items

Specifies the item collection used by declarative axis and series selectors.

IEnumerable<TItem>null
Options

Specifies chart rendering options.

SvgChartOptionsnull
Role

Specifies the root SVG role used by assistive technologies.

string"img"
Streaming

Specifies chart streaming options.

SvgChartStreamingOptionsnull
TabIndex

Specifies the root SVG tabindex when keyboard focus should be enabled.

int?null
Type

Specifies the chart rendering type.

Possible values:Column, Bar, Line, Area, Pie, Doughnut, PolarArea, Radar, Scatter, Bubble

SvgChartTypeSvgChartType.Column

SvgChartStreamingOptions

Parameter Description TypeDefault
Animation

Defines streaming animation options.

SvgChartStreamingAnimationOptionsnew()
Duration

Defines the maximum time span to keep. When null, points are not trimmed by duration and retention is unlimited unless limited by MaxDataPoints.

TimeSpan?null
Enabled

Defines whether streaming behavior is enabled.

booltrue
IndexAxis

Defines the axis used for the streaming index.

Possible values:X, Y

SvgChartIndexAxisSvgChartIndexAxis.X
MaxDataPoints

Defines the maximum number of data points to keep. When null, points are not trimmed by count.

int?null
RefreshInterval

Defines the minimum time between chart redraws while streaming.

TimeSpanTimeSpan.Zero
Reverse

Defines whether the streaming index axis is reversed.

boolfalse
VisibleDataPoints

Defines the number of data points visible in the streaming viewport. When null, all retained points are visible.

int?null

SvgChartStreamingAnimationOptions

Parameter Description TypeDefault
Duration

Defines the animation duration used when the streaming viewport advances. When zero, the refresh interval is used.

TimeSpanTimeSpan.Zero
Enabled

Defines whether the streaming viewport should animate between appended values.

booltrue

Events

SvgChart

Event Description Type
Clicked

Occurs when a rendered chart point is clicked.

EventCallback<SvgChartPointEventArgs>
Hovered

Occurs when a rendered chart point is hovered.

EventCallback<SvgChartPointEventArgs>

Methods

SvgChart

Method DescriptionReturnParameters
AddLabel Adds a category label to the chart data. Taskobject label
AddSeries Adds a data series to the chart. TaskSvgChartSeriesData<double?> series
AddValue Adds a value to an existing data series. Taskstring seriesName, double? value
AppendValues Appends streamed values to matching series and adds the label as the next category. Taskobject label, IReadOnlyDictionary<string, double?> values
AppendValue Appends a streamed value to a series and adds the label as the next category. Taskstring seriesName, object label, double? value
Clear Clears chart labels, values, visibility state, tooltip state, viewport, and streaming state. Task
HideDataPoint Hides a visible radial data point. Taskstring seriesName, int pointIndex
HideSeries Hides a visible data series. Taskstring seriesName
PauseStreaming Pauses accepting streamed values. Task
RemoveSeries Removes a data series by name. Taskstring name
ResetZoom Resets the chart zoom viewport. Task
Resize Refreshes the chart after its container size changes. Task
ResumeStreaming Resumes accepting streamed values. Task
SetData Replaces the chart data and refreshes the chart. TaskSvgChartData<double?> data
SetMaxDataPoints Updates the maximum number of streamed data points to keep. Taskint? maxDataPoints
SetOptions Replaces the chart options and refreshes the chart. TaskSvgChartOptions options
SetValue Updates a value in an existing data series. Taskstring seriesName, int index, double? value
SetViewport Sets the active chart viewport. TaskSvgChartViewport viewport
ShowDataPoint Shows a hidden radial data point. Taskstring seriesName, int pointIndex
ShowSeries Shows a hidden data series. Taskstring seriesName
ToSvgString Exports the chart root SVG markup as a string. ValueTask<string>
ToggleDataPoint Toggles the visibility of a radial data point. Taskstring seriesName, int pointIndex
ToggleSeries Toggles the visibility of a data series. Taskstring seriesName
Update Refreshes the chart. Task
ZoomIn Zooms into the chart from the center of the plot area. Task
ZoomOut Zooms out from the center of the plot area. Task
On this page