当前位置:网站首页>WPF 自定义 写实风 雷达图控件
WPF 自定义 写实风 雷达图控件
2022-07-08 00:16:00 【不知名君】
WPF 自定义 写实风 雷达图控件
控件主要使用Transform实现控件的旋转绘制
先来张图Look Look。。。
XAMl:
<UserControl.Resources>
<Style TargetType="Line">
<Setter Property="Stroke" Value="#AB72D458"/>
<Setter Property="X1" Value="0"/>
<Setter Property="Y1" Value="0"/>
<Setter Property="X2" Value="1"/>
<Setter Property="Y1" Value="0"/>
<Setter Property="Stretch" Value="Fill"/>
<Setter Property="StrokeThickness" Value="1"/>
<Setter Property="RenderTransformOrigin" Value="0.5,0.05"/>
</Style>
</UserControl.Resources>
<Grid Margin="8" x:Name="RadarGrid" Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}">
<Ellipse Margin="-8" StrokeThickness="8">
<Ellipse.Stroke>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#777777"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Stroke>
<Ellipse.Effect>
<DropShadowEffect ShadowDepth="4" BlurRadius="20" Direction="-90" Color="#B6B4B4"/>
</Ellipse.Effect>
</Ellipse>
<!--#region 底图 -->
<Ellipse>
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="#FF02AE03"/>
<GradientStop Color="#FF034300" Offset="0.904"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!--#endregion-->
<!--#region 扫描线 -->
<!--<Grid RenderTransformOrigin="0.5,0.5">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="ScanEllipse" Duration="0:0:2"
Storyboard.TargetProperty="Angle" From="0" To="360"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid.RenderTransform>
<RotateTransform x:Name="ScanEllipse"/>
</Grid.RenderTransform>
<Line X1="0" Y1="0" X2="1" Y2="0" StrokeThickness="4" StrokeDashCap="Round" StrokeDashArray="{x:Null}" Stretch="Fill">
<Line.Stroke>
<LinearGradientBrush EndPoint="1,0" StartPoint="0,0">
<GradientStop Color="#FFC5FFB6" Offset="0.008"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Line.Stroke>
<Line.Effect>
<BlurEffect/>
</Line.Effect>
</Line>
</Grid>-->
<!--#endregion-->
<Line/>
<Line>
<Line.RenderTransform>
<RotateTransform Angle="30"/>
</Line.RenderTransform>
</Line>
<Line>
<Line.RenderTransform>
<RotateTransform Angle="60"/>
</Line.RenderTransform>
</Line>
<Line>
<Line.RenderTransform>
<RotateTransform Angle="90"/>
</Line.RenderTransform>
</Line>
<Line>
<Line.RenderTransform>
<RotateTransform Angle="120"/>
</Line.RenderTransform>
</Line>
<Line>
<Line.RenderTransform>
<RotateTransform Angle="150"/>
</Line.RenderTransform>
</Line>
<Ellipse Stroke="#FF0C6703" StrokeThickness="2"/>
<Ellipse Stroke="#E4A0F424" Margin="50"/>
<Ellipse Stroke="#C3A0F424" Margin="100"/>
<Ellipse Stroke="#9EA0F424" Margin="150"/>
<Ellipse Stroke="#AEA0F424" Margin="200"/>
<Ellipse Fill="#AEA0F424" Width="10" Height="10"/>
<Grid x:Name="dataGrid"/>
<!--<TextBlock Text="10" VerticalAlignment="Center" Foreground="{StaticResource MahApps.Brushes.ThemeBackground}" Margin="0" />
<TextBlock Text="8" VerticalAlignment="Center" Foreground="{StaticResource MahApps.Brushes.ThemeBackground}" Margin="48" />
<TextBlock Text="6" VerticalAlignment="Center" Foreground="{StaticResource MahApps.Brushes.ThemeBackground}" Margin="98" />
<TextBlock Text="4" VerticalAlignment="Center" Foreground="{StaticResource MahApps.Brushes.ThemeBackground}" Margin="148"/>
<TextBlock Text="2" VerticalAlignment="Center" Foreground="{StaticResource MahApps.Brushes.ThemeBackground}" Margin="198"/>-->
</Grid>
C#:
/// <summary>
/// RadarChart.xaml 的交互逻辑
/// </summary>
public partial class RadarChart : UserControl
{
public RadarChart()
{
InitializeComponent();
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
Refresh();
}
public ObservableCollection<RadarData> RadarDatas
{
get {
return (ObservableCollection<RadarData>)GetValue(RadarDatasProperty); }
set {
SetValue(RadarDatasProperty, value); }
}
public static readonly DependencyProperty RadarDatasProperty =
DependencyProperty.Register("RadarDatas", typeof(ObservableCollection<RadarData>), typeof(RadarChart), new PropertyMetadata(null, OnDataChanged));
private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var sen = (d as RadarChart);
if (sen.RadarDatas != null)
{
sen.RadarDatas.CollectionChanged += (s, er) => sen.Refresh();
}
}
private const double maxDistance = 10;
private void Refresh()
{
dataGrid.Children.Clear();
if (RadarDatas == null)
{
return;
}
Point center = new Point(RadarGrid.ActualHeight / 2, RadarGrid.ActualWidth / 2);
foreach (var item in RadarDatas)
{
if (item.Distance > maxDistance)
{
continue;
}
ContentControl contentControl = new ContentControl() {
Width = 30, Height = 30 };
double locat = 0;
if (item.Distance != 0)
{
locat = item.Distance / maxDistance * (RadarGrid.ActualHeight + contentControl.Width) / 2 - (contentControl.Width / 2);
}
// 图形化的显示内容
item.Content.HorizontalAlignment = HorizontalAlignment.Center;
item.Content.VerticalAlignment = VerticalAlignment.Center;
contentControl.Content = item.Content;
TranslateTransform translate = new TranslateTransform() {
Y = -locat };
contentControl.RenderTransform = translate;
contentControl.Foreground = Brushes.White;
// 显示当前距离的文本
TextBlock textBlock = new TextBlock() {
Text = item.Distance.ToString("f1")};
textBlock.VerticalAlignment = VerticalAlignment.Bottom;
textBlock.FontSize = 14d;
textBlock.HorizontalAlignment = HorizontalAlignment.Center;
TranslateTransform translateText = new TranslateTransform() {
Y = -locat / 2 };
RotateTransform rotateText = new RotateTransform(-item.Angle);
TransformGroup group = new TransformGroup();
group.Children.Add(rotateText);
group.Children.Add(translateText);
textBlock.RenderTransform = group;
textBlock.Foreground = Brushes.White;
// 划线
Line line = new Line() {
X1 = 0, Y1 = 0, X2 = 0, Y2 = 1, Width = 0d,Height=0d};
var lineHeight = item.Distance / maxDistance * (RadarGrid.ActualHeight + contentControl.Width) / 2 - (contentControl.Width / 2);
if (lineHeight > contentControl.Width)
{
line.Height = item.Distance / maxDistance * (RadarGrid.ActualHeight + contentControl.Width) / 2 - (contentControl.Width / 2);
line.Width = item.Distance / maxDistance * (RadarGrid.ActualHeight + contentControl.Width) / 2;
}
line.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#9EBE0E19"));
line.StrokeThickness = 3;
line.VerticalAlignment = VerticalAlignment.Bottom;
line.HorizontalAlignment = HorizontalAlignment.Center;
Grid lineGrid = new Grid();
lineGrid.RowDefinitions.Add(new RowDefinition());
lineGrid.RowDefinitions.Add(new RowDefinition());
lineGrid.Children.Add(line);
lineGrid.Children.Add(textBlock);
Grid grid = new Grid();
RotateTransform rotate = new RotateTransform() {
Angle = item.Angle };
grid.RenderTransformOrigin = new Point(0.5, 0.5);
grid.RenderTransform = rotate;
grid.Children.Add(contentControl);
grid.Children.Add(lineGrid);
dataGrid.Children.Add(grid);
}
}
}
public class RadarData
{
public double Angle {
get; set; }
public double Distance {
get; set; }
public FrameworkElement Content {
get; set; }
}
测试使用数据:
double testdis = 10;
double testdis1 = 0;
double testdis2 = 5;
/// <summary>
/// 测试雷达图
/// </summary>
void TestRadar()
{
testdis = testdis <= 1 ? 10 : testdis;
testdis1 = testdis1 >= 9 ? 0 : testdis1;
testdis2 = testdis2 >= 9 ? 0 : testdis2;
RadarTestData.Clear();
testdis -= 0.02;
RadarData data = new RadarData()
{
Angle = -30,
Distance = testdis,
Content = new PackIconMaterial() {
Width = 30, Foreground = Brushes.Red, Height = 30, Kind = PackIconMaterialKind.Run },
};
RadarTestData.Add(data);
testdis1 += 0.02;
RadarData data1 = new RadarData()
{
Angle = 120,
Distance = testdis1,
Content = new PackIconMaterial() {
Width = 20, Foreground = Brushes.Red, Height = 20, Kind = PackIconMaterialKind.Archive },
};
RadarTestData.Add(data1);
testdis2 += 0.02;
RadarData data2 = new RadarData()
{
Angle = 45,
Distance = testdis2,
Content = new PackIconMaterial() {
Width = 20, Foreground = Brushes.Red, Height = 20, Kind = PackIconMaterialKind.AlarmLight },
};
RadarTestData.Add(data2);
}
边栏推荐
- Usage of hydraulic rotary joint
- 【SolidWorks】修改工程图格式
- Capability contribution three solutions of gbase were selected into the "financial information innovation ecological laboratory - financial information innovation solutions (the first batch)"
- break net
- Codeforces Round #643 (Div. 2)——B. Young Explorers
- Gnuradio operation error: error thread [thread per block [12]: < block OFDM_ cyclic_ prefixer(8)>]: Buffer too small
- Qml 字体使用pixelSize来自适应界面
- Codeforces Round #643 (Div. 2)——B. Young Explorers
- 2、TD+Learning
- 正则表达式
猜你喜欢
随机推荐
ROS problems (topic types do not match, topic datatype/md5sum not match, MSG XXX have changed. rerun cmake)
ArrayList源码深度剖析,从最基本的扩容原理,到魔幻的迭代器和fast-fail机制,你想要的这都有!!!
3、多智能体强化学习
COMSOL - Construction of micro resistance beam model - final temperature distribution and deformation - establishment of geometric model
Understanding of maximum likelihood estimation
能力贡献 GBASE三大解决方案入选“金融信创生态实验室-金融信创解决方案(第一批)”
The persistence mode of redis - RDB and AOF persistence mechanisms
Codeforces Round #633 (Div. 2) B. Sorted Adjacent Differences
Mat file usage
Redis cluster
【目标跟踪】|atom
What kind of MES system is a good system
STM32GPIO口的工作原理
Scalar / vector / matrix derivation method
Tapdata 的 2.0 版 ,開源的 Live Data Platform 現已發布
Probability distribution
滑环在直驱电机转子的应用领域
powerbuilder 中使用线程的方法
Plot function drawing of MATLAB
Different methods for setting headers of different pages in word (the same for footer and page number)