I have a requirement to plot a chart as shown in the attachment. I saw a Syncfusion kb for Violin Plot for WPF. May I know how to achieve the attached design (Violin Plot) in Xamarin Forms using SfChart?
|
<local:ChartExt ">
<chart:BoxAndWhiskerSeries ItemsSource="{Binding BoxWhiskerData}"
XBindingPath="Department" ShowOutlier="False"
YBindingPath="Age" Width="0.2"
BoxPlotMode="Normal"/>
</local:ChartExt> |
|
public class CustomChart : SfChartExt
{
public CustomChart(Android.Content.Context context) : base(context)
{
}
protected override Com.Syncfusion.Charts.ChartSeries CreateNativeChartSeries(Syncfusion.SfChart.XForms.ChartSeries formSeries)
{
if (formSeries is Syncfusion.SfChart.XForms.BoxAndWhiskerSeries)
{
return new CustomBoxAndWhiskerSeries();
}
return base.CreateNativeChartSeries(formSeries);
}
}
public class CustomBoxAndWhiskerSeries : Native.BoxAndWhiskerSeries
{
protected override Native.ChartSegment CreateSegment()
{
CustomBoxAndWhiskerSegment segment = new CustomBoxAndWhiskerSegment();
SetInternalProperty(typeof(Native.BoxAndWhiskerSegment), segment, "Series", this);
return segment;
}
}
public class CustomBoxAndWhiskerSegment : Native.BoxAndWhiskerSegment
{
Paint paint = new Paint();
public override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
BoxAndWhiskerSegment baseSegment = this as BoxAndWhiskerSegment;
float Left = (float)GetInternalProperty("Left", baseSegment);
float Right = (float)GetInternalProperty("Right", baseSegment);
float Top = (float)GetInternalProperty("Top", baseSegment);
float Bottom = (float)GetInternalProperty("Bottom", baseSegment);
PointF Center = (PointF)GetInternalProperty("AveragePoint", baseSegment);
PointF minimumPoint = (PointF)GetInternalProperty("MinimumPoint", baseSegment);
PointF medianPoint = (PointF)GetInternalProperty("MedianPoint", baseSegment);
PointF maximumPoint = (PointF)GetInternalProperty("MaximumPoint", baseSegment);
var tlPoint = new PointF((int)Left, (int)Top);
var brPoint = new PointF((int)Right, (int)Bottom);
var centre = tlPoint.X + (brPoint.X - tlPoint.X) / 2;
var rect = new Rect((float)(centre - 2.5), tlPoint.Y, (float)(centre + 2.5), brPoint.Y);
var centerLinePosition = rect.Left + rect.Width() / 2;
float extensionValue = 25;
paint.StrokeWidth = 2;
paint.Color = Android.Graphics.Color.Blue;
paint.SetStyle(Paint.Style.Stroke);
Path path = new Path();
path.MoveTo(centerLinePosition, minimumPoint.Y + (extensionValue * 2));
path.QuadTo( tlPoint.X + (centerLinePosition - tlPoint.X) / 2 - extensionValue, brPoint.Y + (minimumPoint.Y - brPoint.Y) / 2, tlPoint.X - (extensionValue * 2), brPoint.Y);
path.QuadTo(tlPoint.X , tlPoint.Y + (brPoint.Y - tlPoint.Y) / 2, tlPoint.X - (extensionValue * 2), tlPoint.Y);
path.QuadTo(centerLinePosition - (centerLinePosition - tlPoint.X)/2 - extensionValue, maximumPoint.Y + (tlPoint.Y - maximumPoint.Y)/2, centerLinePosition, maximumPoint.Y - (extensionValue * 2));
path.QuadTo(centerLinePosition + (brPoint.X - centerLinePosition) / 2 + extensionValue, maximumPoint.Y + (tlPoint.Y - maximumPoint.Y) / 2, brPoint.X + (extensionValue * 2), tlPoint.Y );
path.QuadTo(centerLinePosition + (centerLinePosition - tlPoint.X) / 2, tlPoint.Y + (brPoint.Y - tlPoint.Y) / 2, brPoint.X + (extensionValue * 2), brPoint.Y);
path.QuadTo(brPoint.X + (centerLinePosition - tlPoint.X) / 2 + extensionValue, brPoint.Y, centerLinePosition, minimumPoint.Y + (extensionValue * 2));
canvas.DrawPath(path, paint);
}
public static object GetInternalProperty(string property, object src)
{
return src.GetType().GetProperty(property, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).
GetValue(src);
}
}
|
Hi,
I have tried using the provided code to obtain violin plot. I have attached a zip file containing the actual violin plot and the violin plot obtained using code. I have modified the code provided (solution attached) with values used for plotting the actual violin plot. Please take a look at the Actual Violin plot attached and revert if it is achievable.