Blazorise SVG Chart Plugins

Extend SVG charts with custom C# and Blazor rendering logic.

SVG chart plugins are child components that register with the chart and render into one of the chart render layers. The chart owns the base layout, axes, scales, series, tooltip state, zoom state, and streaming viewport. Plugins receive a SvgChartPluginRenderContext with resolved chart data, projection helpers, plot bounds, and event helpers.

Built-in SVG chart features are implemented through the same plugin path, including annotations, data labels, trendlines, streaming, and zoom/pan behavior. Users can build their own plugin components by inheriting from SvgChartPluginBase.

Plugins can render SVG directly, read resolved geometry from the render context, project values into plot coordinates, and attach chart events to the elements they create. They are best suited for overlays, annotations, labels, guides, and behavior around an existing chart type. A completely new chart type generally needs a derived chart component and series renderer support in addition to plugin rendering.

Plugin model

  • SvgChartPluginBase registers and unregisters the plugin with the parent chart.
  • Layer controls where the plugin renders relative to the chart body.
  • Render writes SVG elements with RenderTreeBuilder.
  • SvgChartPluginRenderContext provides labels, series, plot bounds, projection helpers, and chart event helpers.
  • RendersContent can be set to false for behavior-only plugins.

Examples

Custom threshold plugin

This example adds a reusable plugin that draws a horizontal threshold line and optional label.
1 series, 7 categories.Service latencyCustom plugin rendered as a series overlay02040608010009:0009:0509:1009:1509:2009:2509:30TargetLatency
<SvgLineChart TItem="LatencySample"
              Items="@samples"
              Options="@options">
    <SvgChartTitle Title='@("Service latency")' Subtitle='@("Custom plugin rendered as a series overlay")' />
    <SvgChartLegend Position="SvgChartLegendPosition.Bottom" />
    <SvgChartTooltip Enabled />
    <SvgChartThresholdLinePlugin Value="80"
                                 Color="Color.Warning"
                                 Label="Target" />
    <SvgChartCategoryAxis Value="@( item => item.Minute )"
                          GridLines="@( new() { Visible = true, Opacity = 0.1 } )"
                          LabelsOptions="@( new() { Step = 1 } )" />
    <SvgChartValueAxis BeginAtZero
                       TickCount="6"
                       GridLines="@( new() { Visible = true, Opacity = 0.14 } )" />

    <SvgLineSeries Name="Latency" Value="@( item => item.Latency )" Color="Color.Primary" MarkerRadius="4" />
</SvgLineChart>
@code {
    private readonly SvgChartOptions options = new()
    {
        Height = 360,
        Legend = new() { Position = SvgChartLegendPosition.Bottom },
    };

    private readonly List<LatencySample> samples =
    [
        new() { Minute = "09:00", Latency = 64 },
        new() { Minute = "09:05", Latency = 71 },
        new() { Minute = "09:10", Latency = 78 },
        new() { Minute = "09:15", Latency = 86 },
        new() { Minute = "09:20", Latency = 74 },
        new() { Minute = "09:25", Latency = 82 },
        new() { Minute = "09:30", Latency = 69 },
    ];

    private sealed class LatencySample
    {
        public string Minute { get; set; }

        public double Latency { get; set; }
    }
}

Plugin component

The plugin inherits from SvgChartPluginBase and renders SVG content using the resolved chart context.
@namespace Blazorise.Docs.Docs.Examples
@inherits SvgChartPluginBase
@using System.Globalization
@using Microsoft.AspNetCore.Components.Rendering

@code {
    /// <summary>
    /// Defines the value where the threshold line is rendered.
    /// </summary>
    [Parameter] public double Value { get; set; }

    /// <summary>
    /// Defines the threshold line color.
    /// </summary>
    [Parameter] public Color Color { get; set; } = Color.Warning;

    /// <summary>
    /// Defines the optional threshold label.
    /// </summary>
    [Parameter] public string Label { get; set; }

    /// <inheritdoc/>
    public override SvgChartRenderLayer Layer => SvgChartRenderLayer.SeriesOverlay;

    /// <inheritdoc/>
    public override void Render( SvgChartPluginRenderContext context, RenderTreeBuilder builder, ref int sequence )
    {
        if ( context.IsRadial )
            return;

        var y = context.ProjectY( Value );
        var color = ResolveColor( Color );

        builder.OpenElement( sequence++, "g" );
        builder.AddAttribute( sequence++, "class", "svg-chart-threshold-line-plugin" );

        builder.OpenElement( sequence++, "line" );
        builder.AddAttribute( sequence++, "x1", Format( context.PlotArea.Left ) );
        builder.AddAttribute( sequence++, "x2", Format( context.PlotArea.Right ) );
        builder.AddAttribute( sequence++, "y1", Format( y ) );
        builder.AddAttribute( sequence++, "y2", Format( y ) );
        builder.AddAttribute( sequence++, "stroke", color );
        builder.AddAttribute( sequence++, "stroke-width", "2" );
        builder.AddAttribute( sequence++, "stroke-dasharray", "6 4" );
        builder.AddAttribute( sequence++, "stroke-linecap", "round" );
        builder.CloseElement();

        if ( !string.IsNullOrWhiteSpace( Label ) )
        {
            builder.OpenElement( sequence++, "text" );
            builder.AddAttribute( sequence++, "x", Format( context.PlotArea.Right - 8 ) );
            builder.AddAttribute( sequence++, "y", Format( y - 8 ) );
            builder.AddAttribute( sequence++, "text-anchor", "end" );
            builder.AddAttribute( sequence++, "font-size", "12" );
            builder.AddAttribute( sequence++, "font-weight", "600" );
            builder.AddAttribute( sequence++, "fill", color );
            builder.AddContent( sequence++, Label );
            builder.CloseElement();
        }

        builder.CloseElement();
    }

    private static string ResolveColor( Color color )
    {
        if ( color is null || color == Color.Default || string.IsNullOrWhiteSpace( color.Name ) )
            return "currentColor";

        var name = color.Name;

        if ( name.StartsWith( "#", StringComparison.Ordinal )
             || name.StartsWith( "rgb", StringComparison.OrdinalIgnoreCase )
             || name.StartsWith( "hsl", StringComparison.OrdinalIgnoreCase )
             || name.StartsWith( "var(", StringComparison.OrdinalIgnoreCase ) )
            return name;

        return $"var(--b-theme-{name}, var(--bs-{name}, currentColor))";
    }

    private static string Format( double value )
    {
        return value.ToString( "0.###", CultureInfo.InvariantCulture );
    }
}

Render layers

Plugins are rendered through SvgChartRenderLayer. Use BeforeSeries for background marks such as ranges and bands, SeriesOverlay for marks that should appear over the series, InteractionOverlay for interactive overlays, and Tooltip for tooltip-level content. The Background layer is available before chart text, grid, and axes are rendered.

API

Methods

Method DescriptionReturnParameters
Render Renders the plugin SVG content into the chart. voidSvgChartPluginRenderContext context, RenderTreeBuilder builder, int sequence
On this page