/// <summary> /// 初始化数据 /// </summary> private void initData() { CanvasPanel.Children.Clear(); if (this.Datas != null && this.Datas.Count > 0) { this.CanvasPanel.Width = this.CanvasPanel.Height = 0; //求角度比例尺 (每个值占多大的角度 可以算到每一块图所占的角度) var angelScale = 360.00 / Datas.Sum(i => i.DataValue); //最大半径 var maxRadius = (MaxSize / 2) - RoseMargin - (ShowValuesLabel ? LabelPathLength : 0); //半径比例尺 (值和比例尺相乘等于每一块图的半径) var radiusScale = maxRadius / Datas.Max(o => o.DataValue); //计算半径宽度值 for (int i = 0; i < Datas.Count; i++) { Datas[i].DataRaidus = Datas[i].DataValue * radiusScale; } //扇形角度初始化 double angleSectorStart = 0; double angleSectorEnd = 0; //循环绘制扇形区域 int scaleTimeSpan = 0; int pathTimespan = 0; int textTimeSpan = 0; for (int index = 0; index < Datas.Count; index++) { //计算扇形角度 if (index == 0) { angleSectorStart = 0; angleSectorEnd = Datas[index].DataValue * angelScale; } else if (index + 1 == Datas.Count) { angleSectorStart += Datas[index - 1].DataValue * angelScale; angleSectorEnd = 360; } else { angleSectorStart += Datas[index - 1].DataValue * angelScale; angleSectorEnd = angleSectorStart + Datas[index].DataValue * angelScale; } var currentRadius = RoseInsideMargin + Datas[index].DataRaidus; //计算扇形点位,用于绘制PATH Point ptOutSideStart = GetPoint(currentRadius, angleSectorStart * Math.PI / 180); Point ptOutSideEnd = GetPoint(currentRadius, angleSectorEnd * Math.PI / 180); Point ptInSideStart = GetPoint(RoseInsideMargin, angleSectorStart * Math.PI / 180); Point ptInSideEnd = GetPoint(RoseInsideMargin, angleSectorEnd * Math.PI / 180); if (string.IsNullOrEmpty(Datas[index].RColor)) { Datas[index].RColor = ChartColorPool.ColorStrings[index]; } Path pthSector = new Path() { Fill = Datas[index].Fill }; //PATH数据格式 M0,100 L50,100 A50,50 0 0 1 100,50 L100,0 A100,100 0 0 0 0,100 Z StringBuilder datastrb = new StringBuilder(); #region BuilderPathData datastrb.Append("M"); datastrb.Append(ptOutSideStart.X.ToString()); datastrb.Append(","); datastrb.Append(ptOutSideStart.Y.ToString()); datastrb.Append(" L"); datastrb.Append(ptInSideStart.X.ToString()); datastrb.Append(","); datastrb.Append(ptInSideStart.Y.ToString()); datastrb.Append(" A"); datastrb.Append(RoseInsideMargin.ToString()); datastrb.Append(","); datastrb.Append(RoseInsideMargin.ToString()); datastrb.Append(" 0 0 1 "); datastrb.Append(ptInSideEnd.X.ToString()); datastrb.Append(","); datastrb.Append(ptInSideEnd.Y.ToString()); datastrb.Append(" L"); datastrb.Append(ptOutSideEnd.X.ToString()); datastrb.Append(","); datastrb.Append(ptOutSideEnd.Y.ToString()); datastrb.Append(" A"); datastrb.Append(currentRadius.ToString()); datastrb.Append(","); datastrb.Append(currentRadius.ToString()); datastrb.Append(" 0 0 0 "); datastrb.Append(ptOutSideStart.X.ToString()); datastrb.Append(","); datastrb.Append(ptOutSideStart.Y.ToString()); datastrb.Append(" Z"); #endregion BuilderPathData try { pthSector.Data = (Geometry) new GeometryConverter().ConvertFromString(datastrb.ToString()); } catch (Exception exp) { } //设置扇形显示的动画 AnimationUtils.FloatElement(pthSector, 1, 200, pathTimespan += 200); AnimationUtils.ScaleRotateEasingAnimationShow(pthSector, 0.1, 1, 1500, scaleTimeSpan += 200, null); CanvasPanel.Children.Add(pthSector); if (ShowValuesLabel) { //计算延伸线角度 double lbPathAngle = angleSectorStart + (angleSectorEnd - angleSectorStart) / 2; //起点 Point ptLbStart = GetPoint(currentRadius, lbPathAngle * Math.PI / 180); //终点 Point ptLbEnd = GetPoint(maxRadius + LabelPathLength, lbPathAngle * Math.PI / 180); Path pthLb = new Path() { Stroke = Datas[index].Stroke, StrokeThickness = 1 }; pthLb.Data = (Geometry) new GeometryConverter().ConvertFromString(string.Format("M{0},{1} {2},{3}", ptLbStart.X.ToString(), ptLbStart.Y.ToString(), ptLbEnd.X.ToString(), ptLbEnd.Y.ToString())); double dur = (textTimeSpan += 200) + 1500; AnimationUtils.CtrlDoubleAnimation(pthLb, 1000, dur); CanvasPanel.Children.Add(pthLb); SetLabel(Datas[index], ptLbEnd, dur); } } this.SizeChanged -= RadarControl_SizeChanged; this.SizeChanged += RadarControl_SizeChanged; } }
private void RadarChartControl_OnLoaded(object sender, RoutedEventArgs e) { if (!CheckData()) { throw new Exception("RadarChart的数据之间不匹配!请重新配置!"); } //获取最大数值 int maxData = Datas.Max(i => i.DataList.Max(o => o.Data)); //设置面板和背景 SetCanvasAndBackground(maxData); //设置数据标题 SetDataTitle(Datas); //获取半圈大小 double length = Size / 2 / maxData; //连接点半径 int ellipseR = EllipseSize / 2; foreach (var chartItem in Datas) { var color = chartItem.Color; //俩个多边形,一个设置背景,一个设置边框 Polygon polygonArea = new Polygon() { Fill = color, Opacity = 0.2, StrokeThickness = 0 }; Polygon polygonBorder = new Polygon() { Fill = Brushes.Transparent, Stroke = color, StrokeThickness = 0.8 }; int index = 0; foreach (var data in chartItem.DataList) { double currentAngle = Angle * index + 90; double angle = (currentAngle / 360) * 2 * Math.PI; var r = data.Data * length; double x = Size / 2 + r * Math.Cos(angle); double y = Size / 2 - r * Math.Sin(angle); //多边形添加节点 var point = new Point() { X = x, Y = y }; polygonArea.Points.Add(point); polygonBorder.Points.Add(point); //设置节点Style var ellipse = new Ellipse() { Width = EllipseSize, Height = EllipseSize, Fill = color }; Canvas.SetLeft(ellipse, x - ellipseR); Canvas.SetTop(ellipse, y - ellipseR); ChartCanvas.Children.Add(ellipse); index++; } ChartCanvas.Children.Add(polygonArea); ChartCanvas.Children.Add(polygonBorder); } //设置标题 SetArguments(); }
/// <summary> /// 设置数据显示 /// </summary> private void InitalData() { CanvasPanel.Children.Clear(); if (Datas != null && Datas.Count > 0) { this.CanvasPanel.Width = this.CanvasPanel.Height = 0; //计算比例尺 var scale = ((MaxSize / 2) - RadarNetMargin) / Datas.Max(i => i.DataValue); //计算实际半径 for (int i = 0; i < Datas.Count; i++) { Datas[i].DataRaidus = Datas[i].DataValue * scale; } //获取最大数值 double maxData = Datas.Max(i => i.DataRaidus); //计算纬线间距半径 double length = maxData / LatitudeCount; for (int index = 1; index < LatitudeCount + 1; index++) { //多边形半径 var r = length * index; Polygon polygonBorder = new Polygon() { Fill = Brushes.Transparent, Stroke = RadarNetBrush, StrokeThickness = RadarNetThickness }; //绘制多边形 for (int currentIndex = 0; currentIndex < Datas.Count; currentIndex++) { double angle = ((Angle * currentIndex + 90) / 360) * 2 * Math.PI; polygonBorder.Points.Add(new Point(r * Math.Cos(angle), r * Math.Sin(angle))); } CanvasPanel.Children.Add(polygonBorder); } //数值区域多边形 Polygon polygonArea = new Polygon() { Fill = AreaBrush, Opacity = 0.5, Stroke = AreaPointBrush, StrokeThickness = 5 }; //经线长度 var maxRadius = LatitudeCount * length; List <Ellipse> ellipselst = new List <Ellipse>(); Dictionary <RadarObj, Point> valuesLabelLocations = new Dictionary <RadarObj, Point>(); Dictionary <RadarObj, Point> groupLabelLocations = new Dictionary <RadarObj, Point>(); //绘制数据多边形 for (int Index = 0; Index < Datas.Count; Index++) { //计算角度 double angle = ((Angle * Index + 90) / 360) * 2 * Math.PI; //计算距离值 var cou = Datas[Index].DataRaidus / length; //计算倍距 var rac = Datas[Index].DataRaidus % length; //计算余距 double Radius = cou * length + rac; //超过最大半径则设置为最大半径 if (Radius > maxRadius) { Radius = maxRadius; } Point pt = new Point(Radius * Math.Cos(angle), Radius * Math.Sin(angle)); polygonArea.Points.Add(pt); valuesLabelLocations.Add(Datas[Index], new Point((Radius) * Math.Cos(angle), (Radius) * Math.Sin(angle))); //记录点位标注标识 //设置数值点,如果数值点尺寸大于0则绘制 if (AreaPointSize > 0) { var ellipse = new Ellipse() { Width = AreaPointSize, Height = AreaPointSize, Fill = AreaPointBrush }; //var ellipse = new Ellipse() { Width = AreaPointSize, Height = AreaPointSize, Fill = Datas[Index].Fill }; AreaPointBrush Canvas.SetLeft(ellipse, pt.X - (AreaPointSize / 2)); Canvas.SetTop(ellipse, pt.Y - (AreaPointSize / 2)); ellipselst.Add(ellipse); } Point ptMax = new Point(maxRadius * Math.Cos(angle), maxRadius * Math.Sin(angle)); //记录组点位标注标识 groupLabelLocations.Add(Datas[Index], new Point((maxRadius + 20) * Math.Cos(angle), (maxRadius + 20) * Math.Sin(angle))); //绘制经线 Path pth = new Path() { Stroke = RadarNetBrush, StrokeThickness = RadarNetThickness }; // Path pth = new Path() { Stroke = Datas[Index].Stroke, StrokeThickness = RadarNetThickness }; pth.Data = (Geometry) new GeometryConverter().ConvertFromString(String.Format("M0,0 {0},{1}", ptMax.X.ToString(), ptMax.Y.ToString())); CanvasPanel.Children.Add(pth); } CanvasPanel.Children.Add(polygonArea); //绘点 foreach (var elc in ellipselst) { CanvasPanel.Children.Add(elc); } //标注值标签 if (ShowValuesLabel) { foreach (var item in valuesLabelLocations) { // SetLabel(item.Key, item.Value, false); } } //标注组标签 if (ShowGroupsLabel) { foreach (var item in groupLabelLocations) { SetLabel(item.Key, item.Value, true); } } this.SizeChanged -= RadarControl_SizeChanged; this.SizeChanged += RadarControl_SizeChanged; } }