# Chart
## Description
A native Blazor charting component: the whole scene - scales, layout, geometry, hit testing - is computed in C# and rendered as plain SVG, so charts work in prerendering and static SSR, need no canvas, and stay crisp at any size. The API mirrors Chart.js: give it a BitChartType plus BitChartData and BitChartOptions (or one BitChartConfig). It draws line, bar, area, pie, doughnut, polar area, radar, scatter, bubble and mixed charts - or a chrome-free sparkline - with multiple axes, stacking, time and log scales, tooltips, data labels, annotations, trendlines, scriptable per-element styling, entry animations and zoom/pan. Refresh() and the visibility API drive it from code for live feeds. Colors follow the bit theme tokens, so every preset and both schemes re-skin it for free; every chart is navigable by keyboard and by touch and ships a visually hidden data table for screen readers, and can hand itself over as SVG, PNG, a data URL or CSV.
## Parameters
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| AriaLabel | `string?` | null | Accessible label for the chart. When null it falls back to the chart title, then to a generated summary. |
| Class | `string?` | null | Custom CSS class applied to the root element of the chart. |
| Config | `BitChartConfig?` | null | Full configuration (type + data + options). Takes precedence over Type/Data/Options when set. |
| Data | `BitChartData?` | null | The chart data: labels and datasets. |
| Dir | `BitDir?` | null | Text direction of the chrome around the plot (title, legend, tooltip and the screen-reader table). The plot keeps its own coordinates; mirror it by setting Reverse on the index scale. |
| ForceAnimation | `bool` | false | Plays the entry and update animations even when reduced motion is requested (prefers-reduced-motion: reduce). By default the chart honors that preference and draws itself straight in its final state. |
| GenerateTable | `bool` | true | Renders a visually-hidden data table for screen readers and points the chart's aria-describedby at it. |
| Height | `string?` | null | Optional CSS height of the chart container. When null the height follows the aspect ratio. |
| HtmlAttributes | `Dictionary<string, object>` | new() | Additional HTML attributes applied to the root element. |
| Id | `string?` | null | The id of the root element of the chart. |
| MaxTableColumns | `int` | 100 | Upper bound on the columns the screen-reader table renders. A value series is one row with a cell per category, so a long one is wide rather than tall and the row cap alone would not contain it. Ignored for scatter and bubble data, whose table is three fixed columns. |
| MaxTableRows | `int` | 500 | Upper bound on the rows the screen-reader table renders, so a long series does not put tens of thousands of hidden nodes in the DOM. Past the limit the caption says how many rows were left out. |
| NavigationHint | `string?` | "Interactive chart. Use the left and right arrow keys..." | A visually hidden sentence telling a screen-reader user how to walk the data, pointed at by aria-describedby alongside the data table. Only rendered when there is data to navigate; set it to null to leave it out. |
| NoDataTemplate | `RenderFragment?` | null | Custom content shown in place of the plot when there is nothing to draw. Takes precedence over NoDataText. |
| NoDataText | `string` | No data to display | Message shown in place of the plot when the configuration produces nothing to draw. |
| OnElementClick | `EventCallback<(int DatasetIndex, int DataIndex)>` | | Callback raised when a data element (point, bar, arc, ...) is clicked, by pointer or with Enter/Space while it is focused. |
| OnElementHover | `EventCallback<BitChartTooltipContext?>` | | Callback raised when the active (hovered or keyboard-focused) element set changes. The context is null once nothing is active. |
| OnLegendItemClick | `EventCallback<BitChartLegendItemModel>` | | Callback raised when a legend item is clicked, before the default visibility toggle runs. |
| OnZoomChange | `EventCallback` | | Callback raised after zoom or pan changes the visible axis ranges. |
| Options | `BitChartOptions?` | null | The chart options: scales, plugins (title, legend, tooltip, data labels), interaction, animation, culture and zoom. |
| Style | `string?` | null | Custom CSS style applied to the root element of the chart. |
| TooltipTemplate | `RenderFragment<BitChartTooltipContext>?` | null | Optional custom tooltip template. When set it replaces the default tooltip body. |
| Type | `BitChartType` | BitChartType.Line | The chart type: Line, Bar, Radar, Pie, Doughnut, PolarArea, Bubble or Scatter. |
| Width | `string` | 100% | CSS width of the chart container. |
## Public Members
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Refresh | `void Refresh()` | | Rebuilds and redraws the chart from its current data and options. Blazor only re-renders on a parameter change it can see, so mutating the same BitChartData in place - appending to a live series, editing a value - needs this call. The counterpart of Chart.js's chart.update(). |
| IsDatasetVisible | `bool IsDatasetVisible(int datasetIndex)` | | Whether a dataset is currently drawn, i.e. hidden neither through the legend nor by BitChartDataset.Hidden. |
| SetDatasetVisible | `void SetDatasetVisible(int datasetIndex, bool visible)` | | Shows or hides a dataset, exactly as clicking its legend entry would; the axes re-scale around what is left. |
| ToggleDataset | `void ToggleDataset(int datasetIndex)` | | Flips a dataset between shown and hidden. |
| IsDataIndexVisible | `bool IsDataIndexVisible(int dataIndex)` | | Whether a data index - a pie, doughnut or polar-area slice - is currently drawn. |
| SetDataIndexVisible | `void SetDataIndexVisible(int dataIndex, bool visible)` | | Shows or hides one data index across the chart, the slice-level counterpart of SetDatasetVisible. |
| ToggleDataIndex | `void ToggleDataIndex(int dataIndex)` | | Flips one data index between shown and hidden. |
| ResetVisibility | `void ResetVisibility()` | | Brings back every dataset and data index hidden through the legend or the API. |
| ResetZoom | `void ResetZoom()` | | Clears every zoom/pan override and returns the chart to the full data range. |
| ZoomTo | `void ZoomTo(string axisId, double? min, double? max)` | | Zooms an axis to an explicit value range, honoring the configured zoom limits. Pass null bounds to clear that axis's override. |
| GetAxisRange | `(double Min, double Max)? GetAxisRange(string axisId)` | | The currently visible range of an axis: its zoomed range when zoomed, otherwise the full data range. |
| ExportSvgAsync | `Task<bool> ExportSvgAsync(string? fileName = null, string? backgroundColor = null)` | | Downloads the chart as a standalone .svg file, with the theme tokens it references resolved into the file. |
| ExportPngAsync | `Task<bool> ExportPngAsync(string? fileName = null, double scale = 2, string? backgroundColor = "#ffffff")` | | Downloads the chart as a .png image rasterized from the live SVG at the given pixel ratio. |
| ExportCsvAsync | `Task<bool> ExportCsvAsync(string? fileName = null)` | | Downloads the chart's data as a .csv file, formatted with the chart's culture. |
| ToCsv | `string ToCsv()` | | Returns the chart's data as CSV text: one row per series for value datasets, one row per point for scatter and bubble datasets. |
| ToSvgStringAsync | `Task<string?> ToSvgStringAsync(string? backgroundColor = null)` | | Returns the chart as standalone SVG markup instead of downloading it, with the theme tokens it references resolved into the markup. Null when the chart has not been rendered in a browser yet. |
| ToBase64ImageAsync | `Task<string?> ToBase64ImageAsync(string mimeType = "image/png", double scale = 2, string? backgroundColor = "#ffffff")` | | Returns the rasterized chart as a data: URL - the same picture ExportPngAsync downloads - ready for an img src or a PDF. Mirrors Chart.js's toBase64Image. |
## Sub Classes
### BitChartConfig Properties
A complete chart configuration bundling the type, data and options.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Type | `BitChartType` | BitChartType.Line | The chart type. |
| Data | `BitChartData` | new() | The labels and datasets. |
| Options | `BitChartOptions` | new() | The scales, plugins, interaction, animation and zoom options. |
### BitChartData Properties
The chart data, mirroring Chart.js data: labels + datasets.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Labels | `List<string>` | new() | The category labels shared by the datasets (used by cartesian, radar, pie and polar charts). |
| Datasets | `List<BitChartDataset>` | new() | The datasets to render. Each dataset carries either a list of values (Data) or points (Points). |
### BitChartDataset Properties
A single dataset, mirroring Chart.js dataset configuration. Colors, radii and styles marked *Fn are scriptable: they receive a BitChartScriptableContext per element and take precedence over the constant beside them.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Label | `string?` | null | Dataset label shown in legends and tooltips. |
| Data | `List<double?>` | new() | Per-index values (line, bar, radar, pie, doughnut, polarArea). A null is a gap, not a zero. |
| Points | `List<BitChartDataPoint>?` | null | Point data (x, y[, r]) for scatter, bubble and time-based line charts. When set, takes precedence over Data. |
| RangeData | `List<(double Low, double High)?>?` | null | Floating-bar ranges per index. When set, bars span low to high instead of growing from the base. |
| Type | `BitChartType?` | null | Optional per-dataset type override, used to build mixed charts. |
| BackgroundColor | `string?` | null | The fill color of the dataset: bars, arcs, points and the area fill of a filled line. |
| BackgroundColors | `List<string>?` | null | One fill color per data index, cycled when shorter than the data. |
| BorderColor | `string?` | null | The line/border color. Bars and arcs fall back to their own fill color rather than an unrelated palette entry. |
| BorderWidth | `double?` | null | Border/line thickness. When null a per-type default applies: 3 for lines and radar, 2 for arcs, and 0 for bars unless a border color was given. |
| Fill | `BitChartFillMode` | BitChartFillMode.None | Area fill mode for line/radar datasets (None, Origin, Start, End, Stack, Dataset, Value). |
| FillGradient | `BitChartGradientBase?` | null | A linear or radial gradient used for the area fill, taking precedence over FillColor and BackgroundColor. |
| BackgroundPattern | `BitChartFillPattern?` | null | A repeating hatch/grid/dot texture used instead of a solid fill; keeps series distinguishable in print and greyscale. |
| Tension | `double` | 0 | Bezier curve tension for line datasets (0 = straight lines). |
| Stepped | `BitChartSteppedLine` | BitChartSteppedLine.False | Draws the line as steps (Before, After or Middle) instead of interpolating. |
| SpanGaps | `bool` | false | Bridges null values instead of breaking the line at them. |
| Segment | `BitChartLineSegmentStyle?` | null | Per-segment color, width and dash callbacks, evaluated from the two endpoints of each segment. |
| PointRadius | `double` | 3 | Marker radius. Zero hides the marker but keeps the point hoverable. |
| PointStyle | `BitChartPointStyle` | BitChartPointStyle.Circle | Marker shape. BitChartPointStyle.None removes the markers - and their hit targets - entirely. |
| Stack | `string?` | null | Stack group id. Datasets sharing an id accumulate together; each group gets its own column. |
| Grouped | `bool` | true | When false the bar dataset leaves the side-by-side layout and keeps the whole category band, so it can sit behind the others. |
| SkipNull | `bool` | false | Lets the remaining bars of a category widen over the datasets that have no value there, instead of leaving a hole. |
| MinBarLength | `double?` | null | Minimum bar length in pixels, so near-zero values stay visible. |
| Base | `double?` | null | The value bars grow from. Defaults to zero clamped into the axis range. |
| BorderRadius | `double` | 0 | Corner radius. On a bar only the corners away from the skipped (baseline) edge are rounded, and BorderRadiusCorners overrides each corner; on a pie, doughnut or polar-area arc it rounds the arc's own corners, clamped to half the ring's thickness. |
| Offset / SpacingArc / HoverOffset | `double` | 0 / 0 / 6 | Arc geometry: how far every slice sits from the center, the gap left between neighbouring slices, and the extra distance the hovered slice pops out. |
| Weight | `double` | 1 | Relative thickness of this dataset's ring in a multi-dataset pie or doughnut. The available radius is shared out in proportion to the weights. |
| ErrorData | `List<BitChartErrorBar?>?` | null | Per-index uncertainty, drawn as a capped whisker through the value and named in the tooltip. A BitChartErrorBar comes from one number (symmetric) or two (asymmetric); a null entry leaves that value bare. Cartesian charts only. |
| ErrorBarColor / ErrorBarWidth / ErrorBarCapWidth | `string? / double / double` | null / 1.5 / 8 | Error-bar styling. A null color follows the primary foreground token; a zero cap width draws a bare whisker. |
| HoverBackgroundColor / HoverBorderColor / HoverBorderWidth | `string? / string? / double?` | null | Styling used while a bar or arc is hovered or keyboard-focused. |
| XAxisID / YAxisID / RAxisID | `string` | x / y / r | The scales this dataset is bound to. Naming a scale that does not exist yet creates a linear one. |
| Order | `int` | 0 | Draw order across datasets; lower draws first. Bars are always drawn before lines and points. |
| Hidden | `bool` | false | Hides the dataset without removing it, and marks its legend entry as toggled off. |
### BitChartOptions Properties
Top-level chart options, mirroring Chart.js options. The same instance can safely be shared between charts: the renderer completes the missing scales locally instead of writing them back.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Responsive | `bool` | true | Observes the container and renders at real device pixels, which keeps font sizes constant at any width. |
| MaintainAspectRatio / AspectRatio | `bool / double?` | true / null | Whether the height follows the width, and the ratio to use. Defaults to 2 for cartesian charts and 1 for circular and radar ones. |
| IndexAxis | `BitChartIndexAxis` | BitChartIndexAxis.X | The axis the data index runs along: X for vertical bars, Y for horizontal ones. |
| Sparkline | `bool` | false | Draws the chart as a sparkline: axes, grid, tick labels, legend, title and subtitle are all dropped so the series fills the box. A presentation switch only - tooltips, keyboard navigation and the screen-reader table still describe the full series. |
| Scales | `Dictionary<string, BitChartScaleOptions>` | new() | Named scales keyed by id (x, y, r, y2, ...): type, min/max, grid, ticks, title, stacking, time unit and radial options. |
| Interaction | `BitChartInteractionOptions` | new() | Mode (Nearest, Index, Dataset, ...) and Intersect. With Intersect false - the default - hit bands make the whole plot hoverable, marked by a crosshair and an axis chip (Crosshair / CrosshairLabel / CrosshairColor). The tooltip inherits Mode and Intersect unless it overrides them. |
| Plugins | `BitChartPluginOptions` | new() | Title, Subtitle, Legend, Tooltip, DataLabels and Decimation options, plus Custom for your own IBitChartPlugin drawing plugins. |
| Animation | `BitChartAnimationOptions` | new() | Duration, easing, per-element stagger (DelayBetween) and the progressive draw-on for line charts. |
| Elements | `BitChartElementOptions` | new() | Per-type defaults used whenever a dataset leaves the matching property unset. |
| Layout | `BitChartLayoutOptions` | new() | Padding around the whole chart. |
| Zoom | `BitChartZoomOptions` | new() | Wheel zoom, drag pan, drag-to-zoom box, axis mode, speed, and the limits that keep the view inside the data. |
| Culture | `CultureInfo?` | null | Culture used for every number and date the chart prints - ticks, tooltips, data labels and the CSV export. Null means the invariant culture. |
| CutoutPercentage / CircumferenceDegrees / RotationDegrees | `double` | 50 / 360 / -90 | Doughnut hole size, sweep and starting angle. A 180 degree sweep turns a doughnut into a gauge. |
### BitChartTrendline Properties
One fitted line drawn over a dataset by BitChartTrendlinePlugin, which is registered through Options.Plugins.Custom. Cartesian charts only.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| DatasetIndex | `int` | 0 | Index of the dataset the line is fitted to. A dataset hidden through the legend takes its trend line with it. |
| Kind | `BitChartTrendlineKind` | BitChartTrendlineKind.Linear | Linear for a least-squares regression, MovingAverage for a trailing average over Period points, or Average for a flat line at the series mean. |
| Period | `int` | 5 | Window of the trailing moving average. Ignored by the other kinds. |
| Extend | `bool` | false | Projects a straight fit out to both edges of the plot instead of stopping at the first and last data point. Ignored by MovingAverage, which has no meaning outside the data. |
| Color / LineWidth / Dash | `string? / double / List<double>?` | null / 2 / [6, 4] | Line styling. A null color follows the dataset's own border color; the dash is what keeps the fit from reading as another measured series - set it to null for a solid line. |
| Label / LabelColor / LabelBackground / LabelFont | `string? / string / string? / BitChartFont` | null / #fff / null / 11px bold | An optional pill drawn at the end of the line, pinned inside the plot so it stays readable at the edge. |
| DrawBehindDatasets | `bool` | false | Draws the line under the datasets rather than over them. |
## Examples
\n**Decimated line (zoom + pan)**:
```razor
```
```csharp
private const int _count = 5000;
private const int _samples = 250;
private BitChartData _data = default!;
private readonly BitChartOptions _options = new()
{
Plugins = new BitChartPluginOptions
{
Legend = new BitChartLegendOptions { Display = false },
// LTTB downsampling keeps thousands of points smooth.
Decimation = new BitChartDecimationOptions { Enabled = true, Samples = _samples, Threshold = 400 },
Tooltip = new BitChartTooltipOptions { Enabled = false }
},
Zoom = new BitChartZoomOptions { Enabled = true, Mode = BitChartZoomMode.X },
Scales = { ["x"] = new BitChartScaleOptions { Id = "x", Type = BitChartScaleType.Time } }
};
protected override void OnInitialized() => _data = BuildLargeSeries(_count);
```
\n**Drag-to-zoom box**:
```razor
```
```csharp
// DragZoom + Wheel = false: drag a rectangle to zoom into it.
private readonly BitChartOptions _drag = new()
{
Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Display = false } },
Zoom = new BitChartZoomOptions { Enabled = true, Mode = BitChartZoomMode.XY, DragZoom = true, Wheel = false }
};
// Scatter(): 400-point random cloud (see "Zoom both axes" card)
```
\n**Category-axis zoom**:
```razor
```
```csharp
private readonly BitChartOptions _catZoom = new()
{
Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Display = false } },
Zoom = new BitChartZoomOptions { Enabled = true, Mode = BitChartZoomMode.X }
};
private BitChartData ManyBars()
{
var rnd = new Random(11);
var labels = Enumerable.Range(1, 40).Select(i => $"D{i}").ToList();
var data = Enumerable.Range(0, 40).Select(_ => (double?)Math.Round(rnd.NextDouble() * 80 + 20, 0)).ToList();
return new BitChartData
{
Labels = labels,
Datasets = { new BitChartDataset { Label = "Daily", Data = data, BackgroundColor = "#4bc0c0" } }
};
}
```
\n**Overview and detail**:
```razor
First quarterWhole series
Showing @_window
@* The overview strip: the same series with nothing but the line. *@
```
```csharp
private BitChart? _brush;
private BitChartData _brushData = default!;
private string _window = "the whole series";
private readonly BitChartOptions _brushOptions = new()
{
Plugins = new BitChartPluginOptions
{
Legend = new BitChartLegendOptions { Display = false },
Decimation = new BitChartDecimationOptions { Enabled = true, Samples = 250, Threshold = 400 }
},
Zoom = new BitChartZoomOptions { Enabled = true, Mode = BitChartZoomMode.X },
Scales = { ["x"] = new BitChartScaleOptions { Id = "x", Type = BitChartScaleType.Time } }
};
private readonly BitChartOptions _overview = new()
{
Sparkline = true,
MaintainAspectRatio = false,
Plugins = new BitChartPluginOptions
{
Decimation = new BitChartDecimationOptions { Enabled = true, Samples = 250, Threshold = 400 },
Tooltip = new BitChartTooltipOptions { Enabled = false }
},
Scales = { ["x"] = new BitChartScaleOptions { Id = "x", Type = BitChartScaleType.Time } }
};
// Zooms the detail chart to a fraction of the full series.
private void ShowWindow(double from, double to)
{
var points = _brushData.Datasets[0].Points!;
double min = points[0].X, span = points[^1].X - min;
_brush!.ZoomTo("x", min + span * from, min + span * to);
}
// OnZoomChange fires after every wheel, drag and ZoomTo, so the readout always matches the view.
private void ReadWindow()
{
// No range means nothing is zoomed - a reset leaves the readout claiming the old window otherwise.
if (_brush?.GetAxisRange("x") is not { } range)
{
_window = "the whole series";
return;
}
_window = $"{DateTime.FromOADate(range.Min):MMM d, HH:mm} to {DateTime.FromOADate(range.Max):MMM d, HH:mm}";
}
```
\n**Streaming updates**:
```razor
@(_timer is null ? "Start" : "Stop")Add one reading
```
```csharp
private const int WindowSize = 40;
private BitChart? _live;
private System.Timers.Timer? _timer;
// One data object, appended to in place - Refresh() is what makes the chart re-read it.
private readonly BitChartData _stream = new()
{
Datasets =
{
new BitChartDataset
{
Label = "Throughput",
BorderColor = "#36a2eb",
FillColor = "rgba(54,162,235,0.15)",
Fill = BitChartFillMode.Origin,
PointRadius = 0,
Tension = 0.3
}
}
};
// A live feed redraws several times a second, so the entry animation is turned off.
private readonly BitChartOptions _streamOptions = new()
{
Animation = new BitChartAnimationOptions { Animate = false },
Scales =
{
["y"] = new BitChartScaleOptions { Id = "y", Type = BitChartScaleType.Linear, BeginAtZero = true, SuggestedMax = 100 }
},
Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Display = false } }
};
private void Toggle()
{
if (_timer is not null) { Stop(); return; }
_timer = new System.Timers.Timer(700) { AutoReset = true };
_timer.Elapsed += async (_, _) => await InvokeAsync(AddReading);
_timer.Start();
}
private void AddReading()
{
Append(); // append one value, drop the oldest
_live?.Refresh(); // rebuild the scene from the data as it now stands
StateHasChanged();
}
```
\n**Showing and hiding series from code**:
```razor
@for (int i = 0; i < _revenue.Datasets.Count; i++)
{
var index = i;
}
Show all
```
```csharp
private BitChart? _visibility;
private readonly BitChartData _revenue = Revenue();
private readonly BitChartOptions _visibilityOptions = new()
{
Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom } }
};
// The same state the legend drives:
// chart.ToggleDataset(i) / SetDatasetVisible(i, visible) / IsDatasetVisible(i)
// chart.ToggleDataIndex(i) for one pie/doughnut/polar-area slice
// chart.ResetVisibility() to bring everything back
```
\n**Culture-aware numbers**:
```razor
```
```csharp
private string _culture = "de-DE";
private BitChartOptions CultureOptions() => new()
{
Culture = CultureInfo.GetCultureInfo(_culture),
Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom } }
};
```
\n**Currency ticks**:
```razor
```
```csharp
private readonly BitChartOptions _currency = new()
{
Culture = CultureInfo.GetCultureInfo("en-US"),
Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom } },
Scales = { ["y"] = new BitChartScaleOptions { Id = "y", Ticks = new BitChartTickOptions { Format = "C0" } } }
};
```
\n**Localized dates**:
```razor
```
```csharp
private string _dateCulture = "fr-FR";
// The culture drives the month and day names on a time axis as well as the numbers.
private BitChartOptions DateOptions() => new()
{
Culture = CultureInfo.GetCultureInfo(_dateCulture),
Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom } },
Scales = { ["x"] = new BitChartScaleOptions { Id = "x", Type = BitChartScaleType.Time } }
};
```
\n**Non-Latin labels**:
```razor
```
```csharp
private readonly BitChartOptions _wide = new()
{
Culture = CultureInfo.GetCultureInfo("ja-JP"),
Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom } },
Scales =
{
["y"] = new BitChartScaleOptions
{
Id = "y",
Title = new BitChartScaleTitleOptions { Display = true, Text = "売上高(百万円)" }
}
}
};
private BitChartData Japanese() => new()
{
Labels = { "東京都", "大阪府", "愛知県", "福岡県", "北海道", "京都府" },
Datasets =
{
new BitChartDataset
{
Label = "今年度",
Data = new() { 320, 245, 198, 162, 140, 121 },
BackgroundColor = "#36a2eb",
BorderRadius = 4
}
}
};
```
\n**Right-to-left**:
```razor
```
```csharp
private readonly BitChartOptions _rtl = new()
{
Plugins = new BitChartPluginOptions
{
Title = new BitChartTitleOptions { Display = true, Text = "فروش فصلی" },
Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom }
},
Scales = { ["x"] = new BitChartScaleOptions { Id = "x", Type = BitChartScaleType.Category, Reverse = true } }
};
private BitChartData Persian() => new()
{
Labels = { "بهار", "تابستان", "پاییز", "زمستان" },
Datasets =
{
new BitChartDataset { Label = "درآمد", Data = new() { 120, 190, 160, 250 }, BackgroundColor = "#4bc0c0", BorderRadius = 4 },
new BitChartDataset { Label = "هزینه", Data = new() { 80, 120, 110, 150 }, BackgroundColor = "#ff9f40", BorderRadius = 4 }
}
};
```
\n**Download the chart**:
```razor
Download SVGDownload PNGDownload CSV
```
```csharp
private BitChart? _chart;
private readonly BitChartOptions _options = new()
{
Plugins = new BitChartPluginOptions
{
Title = new BitChartTitleOptions { Display = true, Text = "Revenue by product" },
Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom }
}
};
private Task ExportSvg() => _chart!.ExportSvgAsync("revenue.svg");
// scale 2 renders at twice the on-screen size, which stays crisp on high-density displays.
private Task ExportPng() => _chart!.ExportPngAsync("revenue.png", scale: 2);
private Task ExportCsv() => _chart!.ExportCsvAsync("revenue.csv");
```
\n**The CSV without downloading it**:
```razor
Show the CSV
@if (_csv is not null)
{
@_csv
}
```
```csharp
private BitChart? _csvChart;
private string? _csv;
private void ShowCsv() => _csv = _csvChart!.ToCsv();
```
\n**The picture without downloading it**:
```razor
Render to a data URLShow the SVG markup
@if (_dataUrl is not null)
{
}
@if (_markup is not null)
{
@_markup
}
```
```csharp
private BitChart? _imageChart;
private string? _dataUrl;
private string? _markup;
// scale 1 matches the on-screen size; pass 2 for a high-density snapshot.
private async Task ShowImage() => _dataUrl = await _imageChart!.ToBase64ImageAsync(scale: 1);
// The theme tokens the chart references are resolved into the markup, so it stands alone.
private async Task ShowMarkup() => _markup = await _imageChart!.ToSvgStringAsync();
```