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

前言

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

由于在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<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);
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<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));
else
drawingContext.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];
else
RadarModels = collectionList[0];
isRefresh = !isRefresh;
}
}
}

效果预览

数据来源于英雄联盟用户

数据1《屈越》

数据2《方拯》

更多教程欢迎关注微信公众号:加微信群限时

WPF开发者QQ群: 340500857

blogs: https://www.cnblogs.com/yanjinhua

源码Github:https://github.com/yanjinhuagood/WPFDevelopers.git

gitee:https://gitee.com/yanjinhua/WPFDevelopers.git

最新文章

  1. Cmder--Windows下命令行利器
  2. JSP+Servlet中使用cos.jar进行图片上传(文件上传亦然)
  3. Linux下查看文件和文件夹大小(转)
  4. PHP+AJAX无刷新返回天气预报
  5. android利用zbar二维码扫描-(解决中文乱码及扫描区域定义)
  6. LeetCode 1. twoSums
  7. 使用PHP实现用户登录和注册的功能
  8. PAT (Advanced Level) 1077. Kuchiguse (20)
  9. discuz开发学习
  10. 201521123091 《Java程序设计》第1周学习总结
  11. 微信小程序开发资源汇总 &#128175;
  12. .net core 在网络高并发下提高JSON的处理效率
  13. 并发系列(5)之 Future 框架详解
  14. 一。Hibernate 开发流程
  15. jdk5升级至jdk8框架版本选型
  16. (转)The Evolved Transformer - Enhancing Transformer with Neural Architecture Search
  17. Java WEB开发环境搭建以及创建Maven Web项目
  18. ELK日志分析平台系统windows环境搭建和基本使用
  19. ThreadLocal使用注意
  20. 黄聪:JQUERY判断操作CHECKBOX选中、取消选中、反选、第二次无法选中的问题

热门文章

  1. 20210804 noip30
  2. struts2执行流程和架构图
  3. vue+element+echarts饼状图+可折叠列表
  4. footer沉底效果
  5. python库--flask--创建嵌套蓝图
  6. js不同地图坐标系经纬度转换(天地图,高德地图,百度地图,腾讯地图)
  7. C语言学习笔记---1.C语言概述
  8. 六种多线程方法解决UI线程堵塞
  9. dede织梦会员模板调用template下模板head.htm方法及解析变量
  10. Shell系列(4)- 历史命令