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

作者:驚鏵 时间:2023-07-13 18:46:53 

前言

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

 

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

由于在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实现雷达图(仿英雄联盟)的示例代码

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

来源:https://www.cnblogs.com/yanjinhua/p/15450989.html

标签:WPF,雷达图
0
投稿

猜你喜欢

  • unity 鼠标悬停事件操作

    2022-12-19 05:36:03
  • Android实现简易秒表功能

    2021-08-29 11:06:58
  • jenkins+Maven从SVN上构建项目的方法

    2022-07-09 04:42:37
  • 使用 BenchmarkDotNet 对 C# 代码进行基准测试

    2023-06-25 00:38:49
  • Android7.0版本影响开发的改进分析

    2022-06-06 03:40:37
  • 详解Java类型擦除机制

    2023-10-29 06:41:21
  • 1秒钟实现Springboot 替换/写入 word文档里面的文字、图片功能

    2022-05-08 18:35:48
  • Java 面试题和答案 - (下)

    2023-10-03 04:46:47
  • 解决Feign获取异常信息的处理方案

    2023-12-11 13:17:54
  • eclipse中maven插件安装教程

    2023-06-23 17:08:23
  • 简单实现安卓里百度地图持续定位

    2023-07-29 07:59:22
  • Spring boot随机端口你都不会还怎么动态扩容

    2021-09-29 10:10:14
  • Java实现微信发红包

    2021-07-22 05:11:07
  • Java中的static关键字你了解多少

    2022-05-21 11:25:51
  • Spring Boot 与DBunit 配合使用方法

    2022-07-29 13:29:28
  • Android开发中的9个常见错误和解决方法

    2023-08-26 16:12:35
  • SpringBoot之Helloword 快速搭建一个web项目(图文)

    2023-08-23 17:36:21
  • 条件数据库Android:sqllite的简单使用

    2023-07-11 15:39:24
  • C#多线程系列之线程池

    2023-02-21 17:25:44
  • C#实现求一组数据众数的方法

    2023-06-07 00:11:53
  • asp之家 软件编程 m.aspxhome.com