WPF实现雷达图(仿英雄联盟)的示例代码

前言

有小伙伴提出需要实现雷达图。 

 

WPF实现雷达图(仿英雄联盟)的示例代码_第1张图片

由于在WPF中没有现成的雷达图控件,所以我们自己实现一个。

PS:有更好的方式欢迎推荐。

实现代码

一、创建 RadarChart.cs 菜单继承 Control代码如下

RadarChart.cs实现思路如下

1、RadarArray :存放展示集合 。

2、重写OnRender 。

3、根据三角函数和圆的半径计算出圆上的N个点绘制成多边形GetPolygonPoint()。

4、在绘制多边形的时候因为需要多个大小不一的多边形,则需要多次调用GetPolygonPoint()方法,最外层绘制150,中间层100,中心点层 50。

5、DrawPoints() 方法增加了一个bool参数isDrawText是否绘制Text文本,因为最外侧需要绘制文本。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
​
namespace WPFDevelopers.Controls
{
    public class RadarChart:Control
    {
        public ObservableCollection RadarArray
        {
            get { return (ObservableCollection)GetValue(RadarArrayProperty); }
            set { SetValue(RadarArrayProperty, value); }
        }
​
        public static readonly DependencyProperty RadarArrayProperty =
            DependencyProperty.Register("RadarArray", typeof(ObservableCollection), typeof(RadarChart), new PropertyMetadata(null));
​
​
        static RadarChart()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(RadarChart), new FrameworkPropertyMetadata(typeof(RadarChart)));
        }
        protected override void OnRender(DrawingContext drawingContext)
        {
            DrawPoints(150, drawingContext,true);
            DrawPoints(100, drawingContext);
            DrawPoints(50, drawingContext);
​
            var myPen = new Pen
            {
                Thickness = 4,
                Brush = Brushes.DodgerBlue
            };
            myPen.Freeze();
            StreamGeometry streamGeometry = new StreamGeometry();
            using (StreamGeometryContext geometryContext = streamGeometry.Open())
            {
                var h = this.ActualHeight / 2;
                var w = this.ActualWidth / 2;
                PointCollection points = new PointCollection();
                foreach (var item in RadarArray)
                {
                    var ss = new Point((item.PointValue.X - w) / 100 * item.ValueMax + w,(item.PointValue.Y - h) / 100 * item.ValueMax + h);
                    points.Add(ss);
                }
                geometryContext.BeginFigure(points[points.Count - 1], true, true);
                geometryContext.PolyLineTo(points, true, true);
            }
            streamGeometry.Freeze();
            SolidColorBrush rectBrush = new SolidColorBrush(Colors.LightSkyBlue);
            rectBrush.Opacity = 0.5;
            drawingContext.DrawGeometry(rectBrush, myPen, streamGeometry);
        }
        void DrawPoints(int circleRadius, DrawingContext drawingContext,bool isDrawText = false)
        {
            var myPen = new Pen
            {
                Thickness = 2,
                Brush = Brushes.Gainsboro
            };
            myPen.Freeze();
            StreamGeometry streamGeometry = new StreamGeometry();
            using (StreamGeometryContext geometryContext = streamGeometry.Open())
            {
                var h = this.ActualHeight / 2;
                var w = this.ActualWidth / 2;
                PointCollection points = null;
                if (isDrawText)
                    points = GetPolygonPoint(new Point(w, h), circleRadius, RadarArray.Count, drawingContext);
                else
                    points = GetPolygonPoint(new Point(w, h), circleRadius, RadarArray.Count);
                geometryContext.BeginFigure(points[points.Count - 1], true, true);
                geometryContext.PolyLineTo(points, true, true);
            }
            streamGeometry.Freeze();
            drawingContext.DrawGeometry(null, myPen, streamGeometry);
        }
        private PointCollection GetPolygonPoint(Point center, double r, int polygonBound, DrawingContext drawingContext = null)
        {
            double g = 18;
            double perangle = 360 / polygonBound;
            double pi = Math.PI;
            List values = new List();
            for (int i = 0; i < polygonBound; i++)
            {
                Point p2 = new Point(r * Math.Cos(g * pi / 180) + center.X, r * Math.Sin(g * pi / 180) + center.Y);
                if(drawingContext != null)
                {
                    FormattedText formattedText = new FormattedText(
                   RadarArray[i].Text,
                   CultureInfo.CurrentCulture,
                   FlowDirection.LeftToRight,
                   new Typeface(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Thin, FontStretches.Normal),
                   20.001D, Brushes.Black)
                    {
                        MaxLineCount = 1,
                        TextAlignment = TextAlignment.Justify,
                        Trimming = TextTrimming.CharacterEllipsis
                    };
                    RadarArray[i].PointValue = p2;
                    if (p2.Y > center.Y && p2.X < center.X)
                        drawingContext.DrawText(formattedText, new Point(p2.X - formattedText.Width - 5, p2.Y - formattedText.Height / 2));
                    else if (p2.Y < center.Y && p2.X > center.X)
                        drawingContext.DrawText(formattedText, new Point(p2.X, p2.Y - formattedText.Height));
                    else if (p2.Y < center.Y && p2.X < center.X)
                        drawingContext.DrawText(formattedText, new Point(p2.X - formattedText.Width - 5, p2.Y - formattedText.Height));
                    else if (p2.Y < center.Y && p2.X == center.X)
                        drawingContext.DrawText(formattedText, new Point(p2.X - formattedText.Width, p2.Y - formattedText.Height));
                    else
                        drawingContext.DrawText(formattedText, new Point(p2.X, p2.Y));
                }
                values.Add(p2);
                g += perangle;
            }
            PointCollection pcollect = new PointCollection(values);
            return pcollect;
        }
    }
}
​

二、创建RadarChartExample.xaml代码如下


    
        
            
                
                    
                    
                
                
                    
                    
                
                
                    
                    
                
                
            
        
    

三、创建RadarChartExample.xaml.cs代码如下

ReadrChartExample.cs 思路如下

1、ValueMax 需要注意最小值0,最大值100。

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using WPFDevelopers.Controls;
​
namespace WPFDevelopers.Samples.ExampleViews
{
    /// 
    /// RadarChartExample.xaml 的交互逻辑
    /// 
    public partial class RadarChartExample : UserControl
    {
        public ObservableCollection RadarModels
        {
            get { return (ObservableCollection)GetValue(RadarModelsProperty); }
            set { SetValue(RadarModelsProperty, value); }
        }
​
        public static readonly DependencyProperty RadarModelsProperty =
            DependencyProperty.Register("RadarModels", typeof(ObservableCollection), typeof(RadarChartExample), new PropertyMetadata(null));
        List> collectionList = new List>();
        public RadarChartExample()
        {
            InitializeComponent();
            RadarModels = new ObservableCollection();
            var collection1 = new ObservableCollection();
            collection1.Add(new RadarModel { Text = "击杀", ValueMax = 95});
            collection1.Add(new RadarModel { Text = "生存", ValueMax = 80 });
            collection1.Add(new RadarModel { Text = "助攻", ValueMax = 70 });
            collection1.Add(new RadarModel { Text = "物理", ValueMax = 80 });
            collection1.Add(new RadarModel { Text = "魔法", ValueMax = 90 });
            collection1.Add(new RadarModel { Text = "防御", ValueMax = 87 });
            collection1.Add(new RadarModel { Text = "金钱", ValueMax = 59 });
​
            var collection2 = new ObservableCollection();
            collection2.Add(new RadarModel { Text = "击杀", ValueMax = 59 });
            collection2.Add(new RadarModel { Text = "生存", ValueMax = 80 });
            collection2.Add(new RadarModel { Text = "助攻", ValueMax = 90 });
            collection2.Add(new RadarModel { Text = "物理", ValueMax = 70 });
            collection2.Add(new RadarModel { Text = "魔法", ValueMax = 80 });
            collection2.Add(new RadarModel { Text = "防御", ValueMax = 90 });
            collection2.Add(new RadarModel { Text = "金钱", ValueMax = 66 });
            collectionList.AddRange(new[] { collection1, collection2 });
            RadarModels = collectionList[0];
        }
        bool isRefresh = false;
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (!isRefresh)
                RadarModels = collectionList[1];
            else
                RadarModels = collectionList[0];
            isRefresh = !isRefresh;
        }
    }
}
​

效果预览

数据来源于英雄联盟用户

数据1《屈越》

数据2《方拯》

WPF实现雷达图(仿英雄联盟)的示例代码_第2张图片

WPF实现雷达图(仿英雄联盟)的示例代码_第3张图片

以上就是WPF实现雷达图(仿英雄联盟)的示例代码的详细内容,更多关于WPF雷达图的资料请关注脚本之家其它相关文章!

你可能感兴趣的:(WPF实现雷达图(仿英雄联盟)的示例代码)