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,一经查实,立即删除!

相关文章

Emoji:搜索将与您找到表情符号背后的故事

眼下。秉已经开始支持emoji搜索&#xff0c;这意味着&#xff0c;你可以插入或粘贴系列emoji表情&#xff0c;让我们的爱、微笑、食品等。。些表情随意组合&#xff0c;必应总会带给你非常多有趣的但却没有不论什么实际用途的搜索结果。这是一项非常新鲜的东西&#xff0c;并且…

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…

TSQL语句中的Like用法

SQL Server&#xff1a;SQL Like 的特殊用法 %&#xff1a;匹配零个及多个任意字符&#xff1b; _&#xff1a;与任意单字符匹配&#xff1b; []&#xff1a;匹配一个范围&#xff1b; [^]&#xff1a;排除一个范围 SymbolMeaninglike 5[%]5%like [_]n_nlike [a-cdf]a, b, c, d…

C++ virtual笔试

一直在赶场&#xff0c;下面是出了N次的题... 当基础看了 #include <iostream> using namespace std; namespace Torxie { // class CFirst { public: void func() { cout<< "CFirst"&l…

这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;但它的数学定义却不…

轻松搭建Google ADK开发环境

相信很多网友一直有自己DIY机器人的想法&#xff0c;但苦于要使用的各种控制模块品种繁多、成本高昂、且开发难度较高。但是随着Google发布了任何人均可自由开发Android终端外设的协议“Open Accessory Protocol”后&#xff0c;大家可以利用Android手机上的丰富资源以及完善的…

搭建nginx + python + django +memcached+ mysql +fastcgi 环境

Django是一个开放源代码的Web应用框 架,由Python写成,它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的。pythondjango也是web开发者最受欢 迎的框架.今天记录下整个搭建开发环境的过程.(说明下环境的系统为 centos 5.2) 一:更新yum仓库(目前这个yu…

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

▲ 点击查看大家好&#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…

C++遍历树-非递归递归-使用了标记位

//这不是最有效的方法&#xff0c;但使用了标记为容易理解&#xff0c;记下 /* * description:树的遍历示例&#xff0c;非递归版本 * 入栈顺序&#xff1a; * 前序&#xff1a; 右子树 - 左子树 - 当前节点 * 中序&#xff1…

模板打印函数

vector的元素可以是任意类型T&#xff0c;但必须具备赋值和拷贝能力&#xff08;具有public 拷贝构造函数和重载的赋值操作符). 其实很容易理解&#xff0c;自定义一些模板时&#xff0c;同样会需要其实例化类型具备默写操作&#xff08;如大于小于操作等。&#xff09; 下面一…

各大厂抢招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 一看就是亲妈&…

mysql数据库属性_mysql - 数据库操作和数据属性

数据库操作启动 mysql, mac 可通过 brew 安装 mysql 后启动。 window 需要手动配置1234567891011121314mysql.server start// windownet start mysql// 登录 -u 用户名 root 超级用户 -p 密码mysql -uroot -p// 退出mysql > q// 切换到 learn 数据库mysql > use learnMyS…

jQuery中,选择器既匹配开头又匹配结尾

jQuery中&#xff0c;选择器既匹配开头又匹配结尾的方法&#xff1a; 1 [attr^val]attr$val 2 [attr^val][attr$val] 转载于:https://www.cnblogs.com/taotaodetuer/p/4790915.html