I want to export my Chart to PNG or JPEG or any image file in the clipboard, so i can copy it to another place with CTRL+V. Here is the code that get the image in base64. Commented code can be ignored but it represent the conversion from base64 to System.Drawing.Image . "ExportChart()" is triggered when a button "Save to clipboard" is clicked and "GetUrl()" is triggered "OnExportComplete".
public async Task ExportChart(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
{
ExportType ExportFileType = ExportType.PNG;
await Chart.ExportAsync(ExportFileType, FileName, null, false);
}
public void GetUrl(ExportEventArgs Args)
{
string dataURL = Args.DataUrl;
//byte[] bytes = Convert.FromBase64String(dataURL);
//System.Drawing.Image image;
//using (MemoryStream ms = new MemoryStream(bytes))
//{
// image = System.Drawing.Image.FromStream(ms);
//}
Clipboard.SetTextAsync(dataURL);
}
Notice that the Clipboard method is not the Windows.Forms class but the Maui.ApplicationModel class. This means that the method "SetImage()" doesn't exist in this context.
Thank you !
Hi Miquel,
Thank you for contacting Syncfusion support.
Currently, in the Syncfusion MAUI chart, we don't have export support. Still, we need some more information about your exact requirement. Can you please clarify the following, so that we can able to proceed further?
Regards,
Ruba Shanmugam
Hello,
Im using Syncfusion Blazor Charts in MAUI Blazor, and also Inputs and ColorPicker.
Here's the code of my page:
@page "/display"
@using Newtonsoft.Json.Linq
@using System.Drawing
<div class="container">
<div class="chart">
<div class="boutons">
<SfButton @onclick="AddChartSeries">sin(x)</SfButton>
<SfButton @onclick="AddChartSeriesDeux">2sin(x)</SfButton>
<SfButton @onclick="AddChartSeriesTrois">1/2*sin(2x)</SfButton>
<SfButton @onclick="RemoveChartSeries">Remove Chart Series</SfButton>
@*Si aucune courbe est selectionnée ou que plus d'une est selectionnée : On désactive le color picker*@
@if(selection==null || selection.Count()==0 || selection.Count()>1){
<SfColorPicker Disabled="true" Mode="ColorPickerMode.Palette" ModeSwitcher="false" ShowButtons="false" ValueChange="OnChange"></SfColorPicker>
}
//Sinon on affiche un color picker avec la valeur de la courbe selectionnée.
else
{
foreach(int i in selection)
{
<SfColorPicker Value="@SeriesCollection[i].color" Mode="ColorPickerMode.Palette" ModeSwitcher="false" ShowButtons="false" ValueChange="OnChange"></SfColorPicker>
}
}
</div>
<SfChart @ref="@Chart" SelectionMode="SelectionMode.Series">
<ChartEvents OnPointClick="@PointClickHandler" OnExportComplete="@GetUrl"></ChartEvents>
<ChartPrimaryXAxis Maximum="@max" Minimum="@min" Interval="5" CrossesAt="0"></ChartPrimaryXAxis>
<ChartPrimaryYAxis Maximum="3" Minimum="-3" CrossesAt="0"></ChartPrimaryYAxis>
<ChartTooltipSettings Enable=@active Shared=true Header="" EnableMarker=false Format="${series.name} <br> X : ${point.x} <br> Y : ${point.y}" Fill="white">
<ChartTooltipBorder Color="rgb(247, 206, 105)" Width="2"></ChartTooltipBorder>
<ChartTooltipTextStyle Color="black"></ChartTooltipTextStyle>
</ChartTooltipSettings>
<ChartSeriesCollection>
@foreach (SeriesData series in SeriesCollection)
{
<ChartSeries [email protected] [email protected] [email protected] Name="@series.name" Width="@series.width" Fill="@series.color" >
<ChartSeriesAnimation Enable="false"></ChartSeriesAnimation>
</ChartSeries>
}
</ChartSeriesCollection>
<ChartAnnotations>
@foreach(LineChartData p in annotations)
{
<ChartAnnotation CoordinateUnits="Units.Point" [email protected] [email protected]()>
<ContentTemplate>
<div>je suis un point</div>
</ContentTemplate>
</ChartAnnotation>
}
</ChartAnnotations>
<ChartLegendSettings Visible="true" ToggleVisibility="true"></ChartLegendSettings>
</SfChart>
</div>
<div id="modif">
<p>Min</p>
<SfNumericTextBox TValue="double" Value="@min" Max="-1" Min="-200">
<NumericTextBoxEvents TValue="double" ValueChange="OnChangeMin"></NumericTextBoxEvents>
</SfNumericTextBox>
<p>Pas</p>
<SfNumericTextBox TValue="double" Value="@pas" Min="0.01" Max="10">
<NumericTextBoxEvents TValue="double" ValueChange="OnChangePas"></NumericTextBoxEvents>
</SfNumericTextBox>
<p>Max</p>
<SfNumericTextBox TValue="double" Value="@max" Max="200" Min="-1">
<NumericTextBoxEvents TValue="double" ValueChange="OnChangeMax"></NumericTextBoxEvents>
</SfNumericTextBox>
<SfButton OnClick="ExportChart" IsToggle="true" IsPrimary="true">
Export
</SfButton>
<SfButton OnClick="activate" IsPrimary="true" IsToggle="true">
Enable trackball
</SfButton>
</div>
</div>
@code{
public List<LineChartData> annotations = new List<LineChartData>();
public bool active = false;
public Dictionary<string,bool> palettes= new Dictionary<string,bool>();
private double pas { get; set; }
private double min { get; set; }
private double max { get; set; }
List<SeriesData> SeriesCollection;
private List<int> selection = new List<int>();
SfChart Chart;
public string FileName { get; set; } = "Graph";
//Change la velur booleene de active quand on active ou desactive la trackball
public void activate(MouseEventArgs args)
{
this.active = !this.active;
}
//Permet d'exporter le Graphique au format png
public async Task ExportChart(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
{
ExportType ExportFileType = ExportType.PNG;
await Chart.ExportAsync(ExportFileType, FileName,null,false);
}
//Permet de recupèrer la base64 du graphique (png)
public void GetUrl(ExportEventArgs Args)
{
string dataURL = Args.DataUrl;
//byte[] bytes = Convert.FromBase64String(dataURL);
//System.Drawing.Image image;
//using (MemoryStream ms = new MemoryStream(bytes))
//{
// image = System.Drawing.Image.FromStream(ms);
//}
Clipboard.SetTextAsync(dataURL);
}
//Permet le changement de couleur en fonction de la couleur selectionnée
public void OnChange(ColorPickerEventArgs args)
{
if(selection.Count()==1){
foreach(int i in selection)
{
SeriesCollection[i].color = args.CurrentValue.Hex;
}
StateHasChanged();
Chart.RefreshAsync();
}
}
//Méthode appelé quand une courbe et cliquée
public void PointClickHandler(PointEventArgs args)
{
//Si le trackball n'est pas afficher :
if (!active)
{
//On récupère son index dans "SeriesCollection"
int i = (int)args.SeriesIndex;
if (selection.Contains(i))
{
SeriesCollection[i].width = 1;
selection.Remove(i);
}
else
{
selection.Add(i);
SeriesCollection[i].width = 2;
}
StateHasChanged();
Chart.RefreshAsync();
}
//Si le trackball est afficher : On ajoute une nouvelle annotation
else
{
double X = (double)args.X;
double Y = (double)args.Y;
annotations.Add(new LineChartData { XValue = X, YValue = Y });
StateHasChanged();
Chart.RefreshAsync();
}
}
//On ajoute la première courbe et on définit sa couleur
public void AddChartSeries()
{
string couleurDispo = "";
foreach(string key in palettes.Keys)
{
if (!palettes[key])
{
couleurDispo = key;
palettes[key] = true;
break;
}
}
SeriesCollection.Add(new SeriesData
{
name="sin(x)",
XName = nameof(LineChartData.XValue),
YName = nameof(LineChartData.YValue),
Data = GetChartData(1),
color=couleurDispo,
width=1
});
}
//On ajoute la deuxième courbe et on définit sa couleur
public void AddChartSeriesDeux()
{
string couleurDispo = "";
foreach(string key in palettes.Keys)
{
if (!palettes[key])
{
couleurDispo = key;
palettes[key] = true;
break;
}
}
SeriesCollection.Add(new SeriesData
{
name="2sin(x)",
XName = nameof(LineChartData.XValue),
YName = nameof(LineChartData.YValue),
Data = GetChartData(2),
color=couleurDispo,
width=1
});
}
//On ajoute la troisième courbe et on définit sa couleur
public void AddChartSeriesTrois()
{
string couleurDispo = "";
foreach(string key in palettes.Keys)
{
if (!palettes[key])
{
couleurDispo = key;
palettes[key] = true;
break;
}
}
SeriesCollection.Add(new SeriesData
{
name = "1/2*sin(x)",
XName = nameof(LineChartData.XValue),
YName = nameof(LineChartData.YValue),
Data = GetChartData(3),
color=couleurDispo,
width=1
});
}
//Au changement du pas
public void OnChangePas(Syncfusion.Blazor.Inputs.ChangeEventArgs<double> args)
{
this.pas = args.Value;
StateHasChanged();
}
//Au changement du min
public void OnChangeMin(Syncfusion.Blazor.Inputs.ChangeEventArgs<double> args)
{
this.min = args.Value;
StateHasChanged();
}
//Au changement du max
public void OnChangeMax(Syncfusion.Blazor.Inputs.ChangeEventArgs<double> args)
{
this.max = args.Value;
StateHasChanged();
}
//Classe permettant de supprimer une series
public void RemoveChartSeries()
{
//Si aucune courbe n'est selectionée, on les supprimes toutes et on dit que sa couleur n'est plus utilisée
if (selection.Count() == 0)
{
foreach(KeyValuePair<string,bool> kvp in palettes)
{
palettes[kvp.Key] = false;
}
SeriesCollection = new List<SeriesData>();
selection = new List<int>();
}
//Sinon on supprrime les courbes sélectionées et on rend leur couleur de nouveau disponibles
else
{
List<SeriesData> Asupprimer = new List<SeriesData>();
foreach(int i in selection)
{
palettes[SeriesCollection[i].color] = false;
}
foreach(int i in selection)
{
Asupprimer.Add(SeriesCollection[i]);
}
foreach(SeriesData s in Asupprimer)
{
SeriesCollection.Remove(s);
}
selection = new List<int>();
}
}
//A l'initialisation de la page
protected override void OnInitialized()
{
base.OnInitialized();
//On ajoute les couleurs par défaut des courbes
palettes.Add("#0000FF", false);
palettes.Add("#FF0000", false);
palettes.Add("#00FF00", false);
//On définit le pas, min et max par défaut de notre graphique
this.pas = 0.1;
this.min = -20;
this.max = 20;
//On instancie la liste des series
SeriesCollection = new List<SeriesData>();
}
//En fonction de la valeur donnée, cette méthode remplis et renvoie une série de donnée correspondante
private List<LineChartData> GetChartData(int courbe)
{
List<LineChartData> data = new List<LineChartData>();
//Si correpond à la courbe 1
if (courbe == 1)
{
for (double i = 0; i <= max; i+=pas)
{
data.Add(new LineChartData()
{
XValue = i,
YValue = Math.Sin(i)
});
}
for (double i = -pas; i >= min; i -= pas)
{
data.Add(new LineChartData()
{
XValue = i,
YValue = Math.Sin(i)
});
}
}//Si la courbe correspond à la 2
else if (courbe == 2)
{
for (double i = 0; i <= max; i+=pas)
{
data.Add(new LineChartData()
{
XValue = i,
YValue = 2*(Math.Sin(i))
});
}
for (double i = -pas; i >= min; i -= pas)
{
data.Add(new LineChartData()
{
XValue = i,
YValue = 2*(Math.Sin(i))
});
}
}//Et enfin si la courbe est la 3ème
else if (courbe == 3)
{
for (double i = 0; i <= max; i+=pas)
{
data.Add(new LineChartData()
{
XValue = i,
YValue = 0.5*(Math.Sin(2*i))
});
}
for (double i = -pas; i >= min; i -= pas)
{
data.Add(new LineChartData()
{
XValue = i,
YValue = 0.5*(Math.Sin(2*i))
});
}
}
List<LineChartData> SortedList = data.OrderBy(o => o.XValue).ToList();
return SortedList;
}
//Classe contenannt les informations relatives à une serie
public class SeriesData
{
public string name
{
get;
set;
}
public string XName
{
get;
set;
}
public string YName
{
get;
set;
}
public List<LineChartData> Data
{
get;
set;
}
public string color
{
get;
set;
}
public int width
{
get;
set;
}
}
//Classe représentant les points du graphique
public class LineChartData
{
public double XValue
{
get;
set;
}
public double YValue
{
get;
set;
}
}
}
Hi Miquel,
We are analyzing your reported scenario. We will update the status within two business days(5th April 2022). We appreciate your patience until then.
Regards,
Durga Gopalakrishnan.
Hi Miquel,
Thanks for being patience.
We have prepared sample to export Syncfusion chart as PNG in .NET MAUI Blazor Application. Chart is exported fine as per behavior. Please check with the below sample and documentation link.
Sample : https://www.syncfusion.com/downloads/support/directtrac/general/ze/MauiApp2090708551.zip
UG : https://blazor.syncfusion.com/documentation/getting-started/maui-blazor-app
Kindly revert us if you have any concerns.
Regards,
Durga Gopalakrishnan.