Charts As Image/Svg
View model
using CommunityToolkit.Mvvm.ComponentModel;
using LiveChartsCore;
using LiveChartsCore.Geo;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
namespace ViewModelsSamples.General.ChartToImage;
public partial class ViewModel : ObservableObject
{
public ISeries[] CatesianSeries { get; set; } =
{
new LineSeries<int> { Values = new int[] { 1, 5, 4, 6 } },
new ColumnSeries<int> { Values = new int[] { 4, 8, 2, 4 } }
};
public ISeries[] PieSeries { get; set; } =
{
new PieSeries<int> { Values = new int[] { 10, } },
new PieSeries<int> { Values = new int[] { 6 } },
new PieSeries<int> { Values = new int[] { 4 } }
};
public IGeoSeries[] GeoSeries { get; set; } = new HeatLandSeries[]
{
new()
{
Lands = new HeatLand[]
{
new() { Name = "bra", Value = 13 },
new() { Name = "mex", Value = 10 },
new() { Name = "usa", Value = 15 },
new() { Name = "can", Value = 8 },
new() { Name = "ind", Value = 12 },
new() { Name = "deu", Value = 13 },
new() { Name= "jpn", Value = 15 },
new() { Name = "chn", Value = 14 },
new() { Name = "rus", Value = 11 },
new() { Name = "fra", Value = 8 },
new() { Name = "esp", Value = 7 },
new() { Name = "kor", Value = 10 },
new() { Name = "zaf", Value = 12 },
new() { Name = "are", Value = 13 }
}
}
};
}
XAML
Having the previous data (ViewModel), we add 3 charts to the UI, a CartesianChart
, a PieChart
and a GeoMap
.
<UserControl
x:Class="UnoWinUISample.General.ChartToImage.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:lvc="using:LiveChartsCore.SkiaSharpView.WinUI"
xmlns:vms="using:ViewModelsSamples.General.ChartToImage"
mc:Ignorable="d">
<UserControl.DataContext>
<vms:ViewModel></vms:ViewModel>
</UserControl.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<lvc:CartesianChart
Grid.Row="0"
x:Name="cartesianChart"
Series="{Binding CatesianSeries}">
</lvc:CartesianChart>
<lvc:PieChart
Grid.Row="1"
x:Name="pieChart"
Series="{Binding PieSeries}">
</lvc:PieChart>
<lvc:GeoMap
Grid.Row="2"
x:Name="geoChart"
Series="{Binding GeoSeries}">
</lvc:GeoMap>
</Grid>
</UserControl>
You will get the following plot in the UI.
You can take any control in the UI and build an image from it, in the next example, for simplicity, we build an image of our charts once the view is loaded.
using LiveChartsCore.SkiaSharpView.SKCharts;
using LiveChartsCore.SkiaSharpView.WinUI;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml;
namespace UnoWinUISample.General.ChartToImage;
public sealed partial class View : UserControl
{
public View()
{
InitializeComponent();
// in this case, when the view is loaded // mark
// we render our chart controls as images // mark
Loaded += View_Loaded;
}
private void View_Loaded(object? sender, RoutedEventArgs e)
{
CreateImageFromCartesianControl();
CreateImageFromPieControl();
CreateImageFromGeoControl();
}
private void CreateImageFromCartesianControl()
{
// you can take any chart in the UI, and build an image from it // mark
var chartControl = (CartesianChart)FindName("cartesianChart");
var skChart = new SKCartesianChart(chartControl) { Width = 900, Height = 600, };
skChart.SaveImage("CartesianImageFromControl.png");
}
private void CreateImageFromPieControl()
{
var chartControl = (PieChart)FindName("pieChart");
var skChart = new SKPieChart(chartControl) { Width = 900, Height = 600, };
skChart.SaveImage("PieImageFromControl.png");
}
private void CreateImageFromGeoControl()
{
var chartControl = (GeoMap)FindName("geoChart");
var skChart = new SKGeoMap(chartControl) { Width = 900, Height = 600, };
skChart.SaveImage("MapImageFromControl.png");
}
}
Build an image in the server side or console app
LiveCharts can render images without the need of any UI framework, you can build images in the server side or in a console application as far as you install the SkiaSharp view package, it is available from NuGet:
LiveChartsCore.SkiaSharpView
Notice any view of LiveCharts (WPF, WinForms, Maui, etc..) has a dependency on LiveChartsCore.SkiaSharpView package, thus you do not need to install this package again if you are already using LiveCharts to render any control in the UI.
The next code block build a CartesianChart
, a PieChart
and a GeoMap
chart as images, to reproduce this sample
create a new ConsoleApplication in VisualStudio 2022, select .Net 6.0 as the framework.
The Net 6.0 template is much cleaner than previous console app templates, notice also that LiveCharts is available in .NET 5.0, .NET core 3.1 or .NET framework (classic) 4.6.2 or greater.
Finally build the images in the Program.cs
file.
using LiveChartsCore;
using LiveChartsCore.Drawing;
using LiveChartsCore.Geo;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.SKCharts;
using LiveChartsCore.SkiaSharpView.VisualElements;
using SkiaSharp;
var cartesianChart = new SKCartesianChart
{
Width = 900,
Height = 600,
Series = new ISeries[]
{
new LineSeries<int> { Values = new int[] { 1, 5, 4, 6 } },
new ColumnSeries<int> { Values = new int[] { 4, 8, 2, 4 } }
},
Title = new LabelVisual
{
Text = "Hello LiveCharts",
TextSize = 30,
Padding = new Padding(15),
Paint = new SolidColorPaint(0xff303030)
},
LegendPosition = LiveChartsCore.Measure.LegendPosition.Right,
Background = SKColors.White
};
// you can save the image to png (by default)
// or use the second argument to specify another format.
cartesianChart.SaveImage("cartesianChart.png");
// additionally you can save a chart as svg:
// for more info see: https://github.com/mono/SkiaSharp/blob/main/tests/Tests/SKCanvasTest.cs#L396
using var stream = new MemoryStream();
var svgCanvas = SKSvgCanvas.Create(SKRect.Create(cartesianChart.Width, cartesianChart.Height), stream);
cartesianChart.DrawOnCanvas(svgCanvas);
svgCanvas.Dispose(); // <- dispose it before using the stream, otherwise the svg could not be completed.
stream.Position = 0;
using var fs = new FileStream("cartesianChart.svg", FileMode.OpenOrCreate);
stream.CopyTo(fs);
// you can also save the image of any other charts:
var pieChart = new SKPieChart
{
Width = 900,
Height = 600,
Series = new ISeries[]
{
new PieSeries<int> { Values = new int[] { 10, } },
new PieSeries<int> { Values = new int[] { 6 } },
new PieSeries<int> { Values = new int[] { 4 } }
},
LegendPosition = LiveChartsCore.Measure.LegendPosition.Right
};
pieChart.SaveImage("pieChart.png");
var geoHeatMap = new SKGeoMap
{
Width = 900,
Height = 600,
Series = new IGeoSeries[]
{
new HeatLandSeries
{
Lands = new HeatLand[]
{
new() { Name = "mex", Value = 10 },
new() { Name = "usa", Value = 15 },
new() { Name = "can", Value = 8 }
}
}
}
};
geoHeatMap.SaveImage("geoHeatMap.png");
// alternatively you can get the image and do different operations:
using var image = cartesianChart.GetImage();
using var data = image.Encode();
var base64CartesianChart = Convert.ToBase64String(data.AsSpan());
Console.WriteLine("Images saved at the root folder!");
Notice that the previous code also works in an ASP.net
project, as far as you are using .NET core 3.1 or greater