Violin Plot using SfChart

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?


Attachment: felt_valued_rating__01.png_e3df2ba5.zip

4 Replies

YP Yuvaraj Palanisamy Syncfusion Team August 27, 2021 03:44 PM UTC

Hi Joseph Cellucci, 
  
Greetings from Syncfusion.  
  
This is a general update to let you know that our support team has taken out your query and they are starting to work on it. We will share the possible workaround solution on or before 31st August 2021.We appreciate your patience until then.  
 
Regards, 
Yuvaraj. 



YP Yuvaraj Palanisamy Syncfusion Team September 1, 2021 02:15 PM UTC

Hi Joesph Cellucci, 
 
Thanks for your patience. 
 
We have achieved your requirement “Violin chart in Xamarin.Forms” by workaround with the help of CustomRenderer in the platform specific project. Please find the code example below. 
 
CodeSnippet: 
<local:ChartExt "> 
 
        <chart:BoxAndWhiskerSeries ItemsSource="{Binding BoxWhiskerData}"   
                               XBindingPath="Department" ShowOutlier="False" 
                               YBindingPath="Age" Width="0.2"  
                               BoxPlotMode="Normal"/> 
</local:ChartExt> 
 
 
Android project [CustomRenderer.cs] 
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); 
    } 
} 
 
 
Also, we have attached the sample for your reference. Please find the sampel from the below link. 
 
  
Output: 
 
 
Regards, 
Yuvaraj.



JC Joseph Cellucci replied to Yuvaraj Palanisamy September 2, 2021 01:02 PM UTC

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.


Attachment: ViolinChart_4a66d89f.zip


YP Yuvaraj Palanisamy Syncfusion Team September 3, 2021 05:18 PM UTC

Hi Joseph Cellucci, 

We have provided the solution with custom drawing in each platform specific based on the BoxAndWhiskerSeries datapoint. You can customize the drawing based on your requirement in the OnDraw method of CustomSegment class as we provided the workaround sample in the kast update. 

Also, you can achieve this by custom view with the help of DataMarker LabelTemplate support in Xamarin.Forms SfChart and you can customize the each datapoint by using DataMarkerLabelCreated event of ChartSeries. 

Also, could you please share us the datapoint plots about the custom drawing in your use case scenario which will be helpful to serve you better solution. 

For more details, please refer the below link. 



Regards, 
Yuvaraj. 


Loader.
Up arrow icon