WPF 雷达图
2021-02-06 22:17
阅读:552
标签:dma series eal asp 记录组 next fill completed split
雷达图逻辑同玫瑰图差不多,不同的地方在于绘制雷达网络,也就是蜘蛛网这样的底图。
界面代码
后台代码
public partial class RadarControl : UserControl { public RadarControl() { InitializeComponent(); } #region 属性 ////// 数值区域填充色 /// public Brush AreaBrush { get { return (Brush)GetValue(AreaBrushProperty); } set { SetValue(AreaBrushProperty, value); } } public static readonly DependencyProperty AreaBrushProperty = DependencyProperty.Register("AreaBrush", typeof(Brush), typeof(RadarControl), new PropertyMetadata(Brushes.Black)); ////// 数值区域点填充色 /// public Brush AreaPointBrush { get { return (Brush)GetValue(AreaPointBrushProperty); } set { SetValue(AreaPointBrushProperty, value); } } public static readonly DependencyProperty AreaPointBrushProperty = DependencyProperty.Register("AreaPointBrush", typeof(Brush), typeof(RadarControl), new PropertyMetadata(Brushes.Black)); ////// 雷达网格线填充充色 /// public Brush RadarNetBrush { get { return (Brush)GetValue(RadarNetBrushProperty); } set { SetValue(RadarNetBrushProperty, value); } } public static readonly DependencyProperty RadarNetBrushProperty = DependencyProperty.Register("RadarNetBrush", typeof(Brush), typeof(RadarControl), new PropertyMetadata(Brushes.Black)); ////// 雷达网格线宽度 /// public double RadarNetThickness { get { return (double)GetValue(RadarNetThicknessProperty); } set { SetValue(RadarNetThicknessProperty, value); } } public static readonly DependencyProperty RadarNetThicknessProperty = DependencyProperty.Register("RadarNetThickness", typeof(double), typeof(RadarControl), new PropertyMetadata(1.0)); ////// 数值点高宽度,0为不显示 /// public double AreaPointSize { get { return (double)GetValue(AreaPointSizeProperty); } set { SetValue(AreaPointSizeProperty, value); } } public static readonly DependencyProperty AreaPointSizeProperty = DependencyProperty.Register("AreaPointSize", typeof(double), typeof(RadarControl), new PropertyMetadata(10.0)); ////// 纬线数量 /// public int LatitudeCount { get { return (int)GetValue(LatitudeCountProperty); } set { SetValue(LatitudeCountProperty, value); } } public static readonly DependencyProperty LatitudeCountProperty = DependencyProperty.Register("LatitudeCount", typeof(int), typeof(RadarControl), new PropertyMetadata(5)); ////// 网格图停靠间距 /// public int RadarNetMargin { get { return (int)GetValue(RadarNetMarginProperty); } set { SetValue(RadarNetMarginProperty, value); } } public static readonly DependencyProperty RadarNetMarginProperty = DependencyProperty.Register("RadarNetMargin", typeof(int), typeof(RadarControl), new PropertyMetadata(50)); ////// 显示值标注 /// public bool ShowValuesLabel { get { return (bool)GetValue(ShowValuesLabelProperty); } set { SetValue(ShowValuesLabelProperty, value); } } public static readonly DependencyProperty ShowValuesLabelProperty = DependencyProperty.Register("ShowValuesLabel", typeof(bool), typeof(RadarControl), new PropertyMetadata(true)); ////// 显示组标签 /// public bool ShowGroupsLabel { get { return (bool)GetValue(ShowGroupsLabelProperty); } set { SetValue(ShowGroupsLabelProperty, value); } } public static readonly DependencyProperty ShowGroupsLabelProperty = DependencyProperty.Register("ShowGroupsLabel", typeof(bool), typeof(RadarControl), new PropertyMetadata(true)); ////// 是否为多重绘图模式(默认否) /// public bool MoreGraphics { get { return (bool)GetValue(MoreGraphicsProperty); } set { SetValue(MoreGraphicsProperty, value); } } public static readonly DependencyProperty MoreGraphicsProperty = DependencyProperty.Register("MoreGraphics", typeof(bool), typeof(RadarControl), new PropertyMetadata(false)); ////// 分隔角度 /// private double Angle { get { int count = MoreGraphics ? MoreDatas[0].Count : Datas.Count; double angle = 360 / count; return angle; } } ////// 数据 /// public ListDatas { get { return (List )GetValue(DatasProperty); } set { SetValue(DatasProperty, value); } } public static readonly DependencyProperty DatasProperty = DependencyProperty.Register("Datas", typeof(List ), typeof(RadarControl), new PropertyMetadata(new List ())); /// /// 多元数据 /// public List[] MoreDatas { get { return (List [])GetValue(MoreDatasProperty); } set { SetValue(MoreDatasProperty, value); } } public static readonly DependencyProperty MoreDatasProperty = DependencyProperty.Register("MoreDatas", typeof(List []), typeof(RadarControl), new PropertyMetadata(new List [2])); /// /// 多元数据画笔 /// public ListRadarNetBrushes { get { return (List )GetValue(RadarNetBrushesProperty); } set { SetValue(RadarNetBrushesProperty, value); } } public static readonly DependencyProperty RadarNetBrushesProperty = DependencyProperty.Register("RadarNetBrushes", typeof(List ), typeof(RadarControl), new PropertyMetadata(new List ())); /// /// 当前绘制大区域 /// private double MaxSize { get { var par = this.Parent as FrameworkElement; return par.ActualHeight > par.ActualWidth ? par.ActualWidth : par.ActualHeight; } } #endregion 属性 private void RadarControl_SizeChanged(object sender, SizeChangedEventArgs e) { if (!MoreGraphics) InitalData(); else InitalMoreData(); } ////// 设置标注 /// /// /// /// private void SetLabel(RadarObj obj, Point location, bool isGroupLabel) { //计算偏移量 bool x = true; bool y = true; if (location.X -5 && location.X -5 && location.Y /// 设置数据显示 /// 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 i.DataRaidus); //计算纬线间距半径 double length = maxData / LatitudeCount; for (int index = 1; index ellipselst = new List(); Dictionary valuesLabelLocations = new Dictionary (); Dictionary groupLabelLocations = new Dictionary (); //绘制数据多边形 for (int Index = 0; Index 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; } } /// /// 设置数据显示 /// private void InitalMoreData() { CanvasPanel.Children.Clear(); if (this.MoreDatas != null && MoreDatas.Length > 0) { this.CanvasPanel.Width = this.CanvasPanel.Height = 0; //计算比例尺 var max = 0.00; foreach (var item in MoreDatas) if (item.Max(i => i.DataValue) > max) max = item.Max(i => i.DataValue); var scale = ((MaxSize / 2) - RadarNetMargin) / max; //计算实际半径 for (int index = 0; index i.DataRaidus) > maxData) maxData = item.Max(i => i.DataRaidus); //计算纬线间距半径 double length = maxData / LatitudeCount; for (int index = 1; index polygonAreaList = new List(); for (int index = 0; index ellipselst = new List (); Dictionary valuesLabelLocations = new Dictionary (); Dictionary groupLabelLocations = new Dictionary (); //绘制数据多边形 for (int Index = 0; Index maxRadius) { Radius = maxRadius; } Point pt = new Point(Radius * Math.Cos(angle), Radius * Math.Sin(angle)); polygonAreaList[dataIndex].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 / 2, Height = AreaPointSize / 2, Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString(ChartColorPool.ColorStrings[Index])) }; Canvas.SetLeft(ellipse, pt.X - (AreaPointSize / 4)); Canvas.SetTop(ellipse, pt.Y - (AreaPointSize / 4)); ellipselst.Add(ellipse); } } Point ptMax = new Point(maxRadius * Math.Cos(angle), maxRadius * Math.Sin(angle)); //记录组点位标注标识 groupLabelLocations.Add(MoreDatas[0][Index], new Point((maxRadius + 20) * Math.Cos(angle), (maxRadius + 20) * Math.Sin(angle))); //绘制经线 RadarNetBrush Path pth = new Path() { Stroke = RadarNetBrush, StrokeThickness = RadarNetThickness }; pth.Data = (Geometry)new GeometryConverter().ConvertFromString(String.Format("M0,0 {0},{1}", ptMax.X.ToString(), ptMax.Y.ToString())); CanvasPanel.Children.Add(pth); } foreach (var polygonArea in polygonAreaList) CanvasPanel.Children.Add(polygonArea); //绘点 foreach (var elc in ellipselst) CanvasPanel.Children.Add(elc); //标注组标签 if (ShowGroupsLabel) { foreach (var item in groupLabelLocations) SetLabel(item.Key, item.Value, true); } this.SizeChanged -= RadarControl_SizeChanged; this.SizeChanged += RadarControl_SizeChanged; } } public void InitalControl() { } /// /// 加载数据 /// /// public void SetData(object dataobj) { if (!MoreGraphics) { this.Datas = (dataobj) as List; this.InitalData(); } else { this.MoreDatas = (dataobj) as List []; InitalMoreData(); } } private Brush _stroke = Brushes.Yellow; /// /// Series stroke /// public Brush Stroke { get { return _stroke; } set { _stroke = value; } } private Brush _fill = Brushes.Yellow; ////// Series Fill /// public Brush Fill { get { return _fill; } set { _fill = value; } } } 调用方式: private void RadarClick(object sender, RoutedEventArgs e) { RadarControl rdc = new RadarControl() { AreaBrush = Brushes.Black, RadarNetBrush = Brushes.Black, AreaPointBrush = Brushes.Orange, BorderBrush = Brushes.Gray }; this.GrdMain.Children.Clear(); this.GrdMain.Children.Add(rdc); rdc.SetData(CrData()); } private void RadarsClick(object sender, RoutedEventArgs e) { RadarControl rdc = new RadarControl() { MoreGraphics = true, AreaBrush = Brushes.Black, RadarNetBrush = Brushes.Black, AreaPointBrush = Brushes.Orange, BorderBrush = Brushes.Gray, RadarNetBrushes = new List{ Brushes.LightSkyBlue, Brushes.Violet } }; this.GrdMain.Children.Clear(); this.GrdMain.Children.Add(rdc); List [] lst = { CrData(), CrData() }; rdc.SetData(lst); } private List CrData() { List list = new List (); list.Add(new RadarObj() { Name="A", DataValue= rdm.Next(20,100) }); list.Add(new RadarObj() { Name = "B", DataValue = rdm.Next(20, 100) }); list.Add(new RadarObj() { Name = "C", DataValue = rdm.Next(20, 100) }); list.Add(new RadarObj() { Name = "D", DataValue = rdm.Next(20, 100) }); list.Add(new RadarObj() { Name = "E", DataValue = rdm.Next(20, 100) }); list.Add(new RadarObj() { Name = "F", DataValue = rdm.Next(20, 100) }); list.Add(new RadarObj() { Name = "F", DataValue = rdm.Next(20, 100) }); return list; }
补充下之前漏掉的辅助类
1.动画辅助类
////// 动画帮助类 /// public class AnimationUtils { ////// 渐影动画 /// /// 控件对象 /// 播放时间长度 /// 延迟播放时间 public static void CtrlDoubleAnimation(UIElement element, double mseconds, double mlateSeconds) { element.Visibility = Visibility.Collapsed; DoubleAnimation doubleAnimation = new DoubleAnimation(); doubleAnimation.From = 0; doubleAnimation.To = 1; doubleAnimation.Duration = TimeSpan.FromMilliseconds(mseconds); EventHandler handler; doubleAnimation.Completed += handler = (s, e) =>{ element.Visibility = Visibility.Visible; }; doubleAnimation.BeginTime = TimeSpan.FromMilliseconds(mlateSeconds); element.BeginAnimation(UIElement.OpacityProperty, doubleAnimation); } ////// 透明度动画 /// /// /// public static void FloatElement(UIElement elem, double to, double mseconds, double mlateSeconds) { lock (elem) { if (to == 1) { elem.Visibility = Visibility.Collapsed; } //else //{ // elem.Visibility = Visibility.Visible; //} DoubleAnimation opacity = new DoubleAnimation() { To = to, Duration = TimeSpan.FromMilliseconds(mseconds), BeginTime = TimeSpan.FromMilliseconds(mlateSeconds) }; EventHandler handler = null; opacity.Completed += handler = (s, e) => { opacity.Completed -= handler; if (to == 1) { elem.Visibility = Visibility.Visible; } //else //{ // elem.Visibility = Visibility.Visible; //} opacity = null; }; elem.BeginAnimation(UIElement.OpacityProperty, opacity); } } ////// 支撑同时旋转和缩放的动画 /// /// 控件 /// 元素开始的大小 /// 元素到达的大小 /// 动画世界 /// 结束事件 public static void ScaleRotateEasingAnimationShow(UIElement element, double from, double to, double mseconds, double mlateSeconds, EventHandler completed) { //旋转 RotateTransform angle = new RotateTransform(); //缩放 ScaleTransform scale = new ScaleTransform(); TransformGroup group = new TransformGroup(); group.Children.Add(scale); group.Children.Add(angle); element.RenderTransform = group; //定义圆心位置 element.RenderTransformOrigin = new Point(0.5, 0.5); EasingFunctionBase easeFunction = new PowerEase() { EasingMode = EasingMode.EaseInOut, Power = 2 }; // 动画参数 DoubleAnimation scaleAnimation = new DoubleAnimation() { From = from, To = to, EasingFunction = easeFunction, Duration = TimeSpan.FromMilliseconds(mseconds), BeginTime = TimeSpan.FromMilliseconds(mlateSeconds), FillBehavior = FillBehavior.Stop }; // 动画参数 DoubleAnimation angleAnimation = new DoubleAnimation() { From = 0, To = 360, EasingFunction = easeFunction, Duration = TimeSpan.FromMilliseconds(mseconds), BeginTime = TimeSpan.FromMilliseconds(mlateSeconds), FillBehavior = FillBehavior.Stop, }; //angleAnimation.Completed += completed; // 执行动画 scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation); scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation); //angle.BeginAnimation(RotateTransform.AngleProperty, angleAnimation); } }
2.标注计算类
////// 计算指定字符串占用的高宽 /// public class ControlSizeUtils { private static Size MeasureTextSize(string text, Typeface typeface, double fontSize) { var ft = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, fontSize, Brushes.Black); return new Size(ft.Width, ft.Height); } ////// 衡量字符尺寸 /// ///public static Size GetTextAreaSize(string text, double fontsize) { FontFamily fontFamily; FontStyle fontStyle; FontWeight fontWeight; FontStretch fontStretch; fontFamily = new FontFamily("微软雅黑"); fontStyle = FontStyles.Normal; fontWeight = FontWeights.Normal; fontStretch = FontStretches.Normal; double fontSize = fontsize; if (text == null) return new Size(0, 0); Typeface typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch); GlyphTypeface gt; if (!typeface.TryGetGlyphTypeface(out gt)) return MeasureTextSize(text, typeface, fontSize); double totalWidth = 0; double totalHeight = 0; // 替换换行符 var array = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); foreach (var splitted in array) { double lineWidth = 0; double lineHeight = 0; // 计算每行的宽度和高度 for (int n = 0; n
3.笔刷集合
public static class ChartColorPool { public static ListColorStrings = new List () { "#FF09F7D7", "#FF97F18E", "#FFF1ADAD", "#FFF44336", "#FFE91E63", "#FF9C27B0", "#FF673AB7", "#FF3F51B5", "#FF2196F3", "#FF03A9F4", "#FF00BCD4", "#FF009688", "#FF4CAF50", "#FF8BC34A", "#FFCDDC39", "#FFFFEB3B", "#FFFFC107", "#FFFF9800", "#FFFF5722", "#FF795548", "#FF9E9E9E", "#FF607D8B", "#32CD32", "#FFFF00", "#32CD32", "#FFFF00", "#21B6BA", "#D84E67", "#B44ED6", "#0092FF", "#E6FF0D", "#21B962", "#FF0000", //[32]Red-纯红 "#00BFFF" , //[33]DeepSkyBlue-深天蓝 "#0099D7",//浅蓝 "#FF9B4D", //橙色 "#00F8A4", //浅绿 "#FFEF53", //黄色 "#EB7274", //粉色 "#8B95AD", //浅灰 "#00DFDE", //浅蓝 "#C19EDC", //浅紫 "#62474C"//褐色 }; }
WPF 雷达图
标签:dma series eal asp 记录组 next fill completed split
原文地址:https://www.cnblogs.com/Funk/p/11405475.html
评论
亲,登录后才可以留言!