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

48 阅读1分钟

中心点层 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 RadarArray

{

get { return (ObservableCollection)GetValue(RadarArrayProperty); }

set { SetValue(RadarArrayProperty, value); }

}

public static readonly DependencyProperty RadarArrayProperty =

DependencyProperty.Register("RadarArray", typeof(ObservableCollection), 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 values = new List();

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="schemas.microsoft.com/winfx/2006/…"

xmlns:x="schemas.microsoft.com/winfx/2006/…"

xmlns:mc="schemas.openxmlformats.org/markup-comp…"

xmlns:d="schemas.microsoft.com/expression/…"

xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"

xmlns:wpfdev="github.com/yanjinhuago…"

mc:Ignorable="d"

d:DesignHeight="450" d:DesignWidth="800">

<Grid.ColumnDefinitions>

</Grid.ColumnDefinitions>

<Grid.RowDefinitions>

</Grid.RowDefinitions>

<wpfdev:RadarChart Grid.Column="0" Grid.Row="1" RadarArray="{Binding RadarModels,RelativeSource={RelativeSource AncestorType=local:RadarChartExample}}"/>

三、创建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

{

///

/// RadarChartExample.xaml 的交互逻辑

///

public partial class RadarChartExample : UserControl

{

public ObservableCollection RadarModels

{

get { return (ObservableCollection)GetValue(RadarModelsProperty); }

set { SetValue(RadarModelsProperty, value); }

}

public static readonly DependencyProperty RadarModelsProperty =

DependencyProperty.Register("RadarModels", typeof(ObservableCollection), typeof(RadarChartExample), new PropertyMetadata(null));

List<ObservableCollection> collectionList = new List<ObservableCollection>();

public RadarChartExample()

{

InitializeComponent();

RadarModels = new ObservableCollection();

var collection1 = new ObservableCollection();

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();

collection2.Add(new RadarModel { Text = "击杀", ValueMax = 59 });

collection2.Add(new RadarModel { Text = "生存", ValueMax = 80 });

collection2.Add(new RadarModel { Text = "助攻", ValueMax = 90 });