WPF实现雷达图(仿英雄联盟)

1f79ba5340d70906fbf3228a7a63c279.png

WPF开发者QQ群: 340500857  | 微信群 -> 进入公众号主页 加入组织

                              转载            

9a3bd60672647745b7e71efeaf34b16d.png 

9b2ca234ae641739b0fc926c58ada69a.png

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

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

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

01

代码如下

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

0f7fbbadf6973711e67e0602e6ca7b98.png

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代码如下

30c151c61e7194667cb8fc049e3a78ba.png

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

1ea54120009e6c00689b7cfbb6bdf135.png

扫一扫关注我们,

9caaefc6989996f4c6548f93e4f5a540.gif

更多知识早知道!

081cce3309f685e58e44a9a502547237.gif

点击阅读原文可跳转至源代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296500.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python3 2.00gb怎么去掉单位_最值得期待的Python 3.9的新功能

Python 3.9 beta预计下个月就要发布了&#xff0c;那么3.9有那些让我们期待的新功能和变更呢&#xff1f;本我我们一起来说Python 3.9的新功能的。安装测试版为了能够实际探索Python 3.9 的功能&#xff0c;我们需要先下载一个Python 3.9 alpha/beta并安装。wget https://www.p…

这6部超经典的物理电影,居然还有人没有看过?

全世界只有3.14 % 的人关注了爆炸吧知识开篇警告&#xff1a;这是一篇福利文&#xff01;今天小编给热爱物理及数学的小伙伴们&#xff0c;分享6部豆瓣评分8分以上&#xff0c;与数学和物理领域相关的经典电影&#xff0c;帮助大家在工作、学习之余劳逸结合。这些影片除了涉及数…

产品说,我只需要一个有亿点复杂的查询界面

有的时候&#xff0c;你需要动态构建一个比较复杂的查询条件&#xff0c;传入数据库中进行查询。而条件本身可能来自前端请求或者配置文件。那么这个时候&#xff0c;表达式树&#xff0c;就可以帮助到你。本文我们将通过几个简短的示例来了解如何完成这些操作。你也可能接到过…

PostgreSQL忘记输入where条件update更新整张表的解决办法

2019独角兽企业重金招聘Python工程师标准>>> 虽然出现这个错误很挫&#xff0c;但有时候还是会被你或者你的同事碰到。为了避免这个错误&#xff0c;PostgreSQL数据库中可以通过触发器来解决&#xff0c;这里用的是plpgsql 。 1、修改postgresql.conf配置 增加&…

视觉开发需要什么程度的数学_角度的概念在视觉上非常直观,但其数学定义并不是那么简单...

角的概念是几何学中最基本的概念之一。当我们研究三角形的性质时&#xff0c;我们自然地建立了三角形的边和角之间的联系。这些联系是在三角学中系统地建立起来的。角是什么&#xff1f;我们如何测量它&#xff1f;虽然角度的概念在视觉上很直观&#xff0c;但它的数学定义却不…

别薅了别薅了!!!再薅就真的被薅秃了!!

▲ 点击查看大家好&#xff0c;超模全新的固定栏目「薅羊毛」上线了&#xff01;既然是薅羊毛&#xff0c;怎么能空着手来&#xff1f;毕竟好用的好吃的&#xff0c;啥都要花钱。与其为那些虚幻的包装价值买单&#xff0c;不如跟着超模君狠狠地薅一把羊毛&#xff0c;「花小钱赚…

GitHub Universe 2021|MS Reactor 邀你共聚年度盛会

关注我们GitHub Universe 2021 将于2021年10月27-28日&#xff08;PDT&#xff09;在线直播&#xff0c;MS Reactor 将与 CSDN 合作进行转播&#xff0c;与你一同观看这场全球开发者盛会。 关于 GitHub UniverseGitHub Universe 是 GitHub 面向全球开发者社区举办的年度重要盛会…

C#中的多线程 - 并行编程 z

原文&#xff1a;http://www.albahari.com/threading/part5.aspx 专题&#xff1a;C#中的多线程 1并行编程Permalink 在这一部分&#xff0c;我们讨论 Framework 4.0 加入的多线程 API&#xff0c;它们可以充分利用多核处理器。 并行 LINQ&#xff08;Parallel LINQ&#xff09…

java数组深拷贝和浅拷贝_java中的深拷贝与浅拷贝(值类型 vs 引用类型)

对象赋值赋值是日常编程过程中最常见的操作&#xff0c;最简单的比如&#xff1a;Student codeSheep new Student(); Student codePig codeSheep;严格来说&#xff0c;这种不能算是对象拷贝&#xff0c;因为拷贝的仅仅只是引用关系&#xff0c;并没有生成新的实际对象&#x…

各大厂抢招WPF,小米这回是下了血本啊...

九银十进入尾声&#xff0c;小米又爆出高薪岗位&#xff1a;35k左右&#xff0c;14薪&#xff0c;招5年左右.NET&#xff0c;要求WPF和自动化( 职位&#xff1a;https://app.mokahr.com/apply/xiaomi/287/#/job/523278c0-c504-4cdc-bb88-28c1b101ac76)。今年招WPF的大厂太多了&…

你永远都不知道你老公可以多幼稚......

1 爸爸带女儿&#xff01;两个幼稚鬼▼2 常州一小区提醒防疫四种语言切换无压力▼3 我知道了&#xff01;他的门牙肯定有条缝▼4 狗子OS&#xff1a;今天栏杆和木棍必须要断一个▼5 掀起你的假发来让我帮你擦擦汗▼6 干啥啥不行&#xff0c;吃饭第一名▼7 一看就是亲妈&…

没有女朋友,可能是因为你数学不好

全世界只有3.14 % 的人关注了爆炸吧知识孔子和耶稣曾说过&#xff1a;初恋无限好。回想起青涩的大学时光&#xff0c;告别了高中时代紧张的学习氛围和父母、老师的谆谆告诫&#xff0c;爱情也不再是伊甸园里的禁果。关于爱情的开展和维系&#xff0c;在Levinger&#xff08;198…

C#10,带来了Date和Time类型

C#10引入了日期DateOnly&#xff0c;时间TimeOnly&#xff1a;//从DateTime转换 Console.WriteLine(DateOnly.FromDateTime(DateTime.Now)); //从字会串转换 Console.WriteLine(DateOnly.Parse("2021-10-23")); //从0001-01-01到现在的天数 Console.WriteLine(DateOn…

数据可视化----我在寻找一款类似vfp或是access这样自带可视化风格的数据库或是键盘数据库...

我在寻找一款类似vfp或是access这样自带可视化风格的数据库或是键盘数据库影响redis,mongodb今后发展的我也认为是一些可视化工具的支持http://blog.xiqiao.info/tag/data-visualization

AgileConfig 1.5 发布 - 支持多环境配置

AgileConfig 从发布到现在&#xff0c;收到不少同学的 issue 说需要多环境的支持。也就是一个应用在不同的环境下可以配置不同的配置项。这是一个非常有用的功能&#xff0c;就跟我们开发的时候会设置多个 appsettings.json 文件一样&#xff0c;比如 appsettings.development.…

知乎高赞:哪些事坚持做3个月就会有巨大改变?

全世界只有3.14 % 的人关注了爆炸吧知识知乎上有个高赞问题&#xff1a;有哪些书看完后&#xff0c;会让人后悔没早看到&#xff1f;答案各有不一、包罗万象。但有一点&#xff0c;大家达成了共识&#xff1a;要多读书。人生漫长&#xff0c;而我们都不会是一成不变的&#xff…

clover 主题_Clover主题更换

小白前言今天,黑果小白来教大家更换自己clover引导的 主题 ,相信大家看了这么久的主题 ,应该也厌倦了吧,换一个主题,增加一下新鲜度,废话不多说,上教程!更换前的准备要想更换主题&#xff0c;你就必须得有主题可以更换&#xff0c;没有主题&#xff0c;神马都是浮云&#xff01…

IOS使用Auto Layout中的VFL适配

做登录页面,之前做都是用frame做,今天想着用Auto Layout中的VFL来做。觉得做的效果还是可以的(自恋一下下)。 首先看下效果图和标记图 自己在做的过程中也遇到了好多问题,不过也一个一个的自己解决了 1.子视图居中的问题 上一博客我也写了,由于指定了视图的宽度高度,想让视图居…

左手菲尔兹右手突破奖,这个中国女婿其实是英国贵族?拿到300万奖金后他这样说……...

全世界只有3.14 % 的人关注了爆炸吧知识如果说科学界里高大上的奖项&#xff0c;你还是只能想到诺贝尔&#xff0c;菲尔兹&#xff0c;那可能真的是out了。毕竟现在都0202年了。少年&#xff0c;突破奖了解一下&#xff1f;作为有马云&#xff0c;马化腾&#xff0c;还有俄罗斯…

理财平台架构分析

一个理财平台可以从不同的维度来看。对于一个消费者来说&#xff0c;最宏观的看法&#xff0c;P2P公司的理财平台相当于一个中介&#xff0c;一边用于对接用户&#xff0c;一边用于对接产品提供商。这个中介系统负责用户和产品提供者之间的交互。对于一个P2P理财公司来说&#…