最近在论坛处理问题中,遇到有用户反馈PointLabelTemplate添加的饼图(pie)的标签,如果数据堆积,则会导致重叠覆盖。
在沟通过程中,陆续通过2个办法尝试解决该问题:
1: c1chart:PlotElement.LabelOffset="30 10"
给所有的Label统一添加一个Offset。
1: <C1Chart:DataSeries.PointLabelTemplate>
2: <DataTemplate>
3: <Border BorderBrush="Gray" C1Chart:PlotElement.LabelAlignment="Auto" >
4: <TextBlock Text="{Binding Value, StringFormat={}{0}%}" />
5: </Border>
6: </DataTemplate>
7: </C1Chart:DataSeries.PointLabelTemplate>
8:
给所有的Label,统一添加对齐方式。
但是,结果不尽如人意。
后来找到《http://helpcentral.componentone.com/nethelp/c1chartSL/#!WordDocuments/chartforsilverlightt.htm》,用PlotElementLoaded事件着手,因为在绘制Pie的时候,每个序列会触发一次PlotElementLoaded事件,我们由此可以获得Pie的区域、相对坐标信息,即可对Label的位置进行编码动态指定,这样就有可能避免标签重叠的问题。
获得Pie的弧度中心点的代码:
1: private Point GetArcCenter(Pie pie)
2: {
3: var path = (Path)pie.Shape;
4: PathGeometry pg = (PathGeometry)path.Data;
5: var pf = pg.Figures[0];
6: var sg0 = (LineSegment)pf.Segments[0];
7: var sg1 = (ArcSegment)pf.Segments[1];
8: var sg2 = (LineSegment)pf.Segments[2];
9:
10: var p0 = pf.StartPoint;
11: var p1 = sg0.Point;
12: var p2 = sg1.Point;
13:
14: var dx = p1.X - p0.X;
15: var dy = p1.Y - p0.Y;
16: var a1 = Math.Atan2(p1.Y - p0.Y, p1.X - p0.X);
17: var a2 = Math.Atan2(p2.Y - p0.Y, p2.X - p0.X);
18: var a = 0.5 * (a1 + a2);
19: if (sg1.IsLargeArc)
20: a += Math.PI;
21: var r = Math.Sqrt(dx * dx + dy * dy);
22:
23: return new Point(Canvas.GetLeft(pie) + p0.X + Math.Cos(a) * r,
24: Canvas.GetTop(pie) + p0.Y + Math.Sin(a) * r);
25: }
另外,当鼠标点击序列区域、Label区域,还可获得序列的数据值。
WPF实现的原理和Silverlight的雷同,请参考WPF相关的在线技术文章:
http://helpcentral.componentone.com/nethelp/c1wpfchart/index.html#!Documents/addingconnectingline.htm
http://helpcentral.componentone.com/nethelp/c1wpfchart/index.html#!Documents/addinglabelstopiecha.htm
http://helpcentral.componentone.com/nethelp/c1wpfchart/index.html#!Documents/changingtheoffsetfor.htm
源代码: