WPF开发者QQ群: 340500857 | 微信群 -> 进入公众号主页 加入组织
转载
有小伙伴提出需要实现雷达图。
由于在WPF中没有现成的雷达图控件,所以我们自己实现一个。
PS:有更好的方式欢迎推荐。
01
—
代码如下
一、创建 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<RadarModel> RadarArray{get { return (ObservableCollection<RadarModel>)GetValue(RadarArrayProperty); }set { SetValue(RadarArrayProperty, value); }}public static readonly DependencyProperty RadarArrayProperty =DependencyProperty.Register("RadarArray", typeof(ObservableCollection<RadarModel>), 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);elsepoints = 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<Point> values = new List<Point>();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));elsedrawingContext.DrawText(formattedText, new Point(p2.X, p2.Y));}values.Add(p2);g += perangle;}PointCollection pcollect = new PointCollection(values);return pcollect;}}
}
二、创建RadarChartExample.xaml代码如下
<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.RadarChartExample"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"xmlns:wpfdev="https://github.com/yanjinhuagood/WPFDevelopers"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"><Grid Background="Gainsboro" ><Border Background="White" Width="500" Height="500"><Grid Margin="20,10"><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition Width="40"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="40"/><RowDefinition/></Grid.RowDefinitions><WrapPanel><Rectangle Width="6" Height="26" Fill="Black"/><TextBlock Text="能力图" FontWeight="Black" FontSize="24" Padding="10,0"/></WrapPanel><wpfdev:RadarChart Grid.Column="0" Grid.Row="1" RadarArray="{Binding RadarModels,RelativeSource={RelativeSource AncestorType=local:RadarChartExample}}"/></Grid></Border></Grid>
</UserControl>
三、创建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
{/// <summary>/// RadarChartExample.xaml 的交互逻辑/// </summary>public partial class RadarChartExample : UserControl{public ObservableCollection<RadarModel> RadarModels{get { return (ObservableCollection<RadarModel>)GetValue(RadarModelsProperty); }set { SetValue(RadarModelsProperty, value); }}public static readonly DependencyProperty RadarModelsProperty =DependencyProperty.Register("RadarModels", typeof(ObservableCollection<RadarModel>), typeof(RadarChartExample), new PropertyMetadata(null));List<ObservableCollection<RadarModel>> collectionList = new List<ObservableCollection<RadarModel>>();public RadarChartExample(){InitializeComponent();RadarModels = new ObservableCollection<RadarModel>();var collection1 = new ObservableCollection<RadarModel>();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<RadarModel>();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];elseRadarModels = collectionList[0];isRefresh = !isRefresh;}}
}
02
—
效果预览
数据来源于英雄联盟用户
数据1《屈越》
数据2《方拯》
源码地址如下
github:https://github.com/yanjinhuagood/WPFDevelopers.git
gitee:https://gitee.com/yanjinhua/WPFDevelopers.git
WPF开发者QQ群: 340500857
blogs: https://www.cnblogs.com/yanjinhua
Github:https://github.com/yanjinhuagood
出处:https://www.cnblogs.com/yanjinhua
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
转载请著名作者 出处 https://github.com/yanjinhuagood
扫一扫关注我们,
更多知识早知道!
点击阅读原文可跳转至源代码