WPF实现雷达图(仿英雄联盟)
生活随笔
收集整理的這篇文章主要介紹了
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);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;}} } ?效果預覽
數據來源于英雄聯盟用戶
數據1《屈越》
數據2《方拯》
總結
以上是生活随笔為你收集整理的WPF实现雷达图(仿英雄联盟)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MongoDB中如何优雅地删除大量数据
- 下一篇: 产品说,我只需要一个有亿点复杂的查询界面