当前位置:网站首页>WPF custom realistic wind radar chart control
WPF custom realistic wind radar chart control
2022-07-08 01:53:00 【Unknown gentleman】
WPF Customize Realism Radar chart control
Control mainly uses Transform Realize the rotation drawing of the control
Let's take a picture first 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 Base map -->
<Ellipse>
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="#FF02AE03"/>
<GradientStop Color="#FF034300" Offset="0.904"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!--#endregion-->
<!--#region Scan line -->
<!--<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 Interaction logic of
/// </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);
}
// Graphical display content
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;
// Display the text of the current distance
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;
// Underline
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; }
}
Test usage data :
double testdis = 10;
double testdis1 = 0;
double testdis2 = 5;
/// <summary>
/// Test radar chart
/// </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);
}
边栏推荐
- MATLAB R2021b 安装libsvm
- Apache多个组件漏洞公开(CVE-2022-32533/CVE-2022-33980/CVE-2021-37839)
- Usage of xcolor color in latex
- Dataworks duty table
- 剑指 Offer II 041. 滑动窗口的平均值
- 快手小程序担保支付php源码封装
- How to realize batch control? MES system gives you the answer
- Apache multiple component vulnerability disclosure (cve-2022-32533/cve-2022-33980/cve-2021-37839)
- Mouse event - event object
- cv2-drawline
猜你喜欢
Redux使用
生态 | 湖仓一体的优选:GBase 8a MPP + XEOS
进程和线程的退出
如何让导电滑环信号更好
保姆级教程:Azkaban执行jar包(带测试样例及结果)
不算不知道,花呗分期的真实利率居然这么高
滑环使用如何固定
Remote Sensing投稿经验分享
Graphic network: uncover the principle behind TCP's four waves, combined with the example of boyfriend and girlfriend breaking up, which is easy to understand
In depth analysis of ArrayList source code, from the most basic capacity expansion principle, to the magic iterator and fast fail mechanism, you have everything you want!!!
随机推荐
ArrayList源码深度剖析,从最基本的扩容原理,到魔幻的迭代器和fast-fail机制,你想要的这都有!!!
The body has a mysterious margin of 8px
从cmath文件看名字是怎样被添加到命名空间std中的
Capability contribution three solutions of gbase were selected into the "financial information innovation ecological laboratory - financial information innovation solutions (the first batch)"
cv2-drawline
COMSOL----微阻梁模型的搭建---最终的温度分布和变形情况---材料的添加
Urban land use distribution data / urban functional zoning distribution data / urban POI points of interest / vegetation type distribution
Qt - - Packaging Programs - - Don't install Qt - can run directly
第七章 行为级建模
从Starfish OS持续对SFO的通缩消耗,长远看SFO的价值
Version 2.0 de tapdata, Open Source Live Data Platform est maintenant disponible
QT build with built-in application framework -- Hello World -- use min GW 32bit
子矩阵的和
Matlab method is good~
[SolidWorks] modify the drawing format
ClickHouse原理解析与应用实践》读书笔记(8)
Usage of hydraulic rotary joint
Apache multiple component vulnerability disclosure (cve-2022-32533/cve-2022-33980/cve-2021-37839)
快手小程序担保支付php源码封装
Partage d'expériences de contribution à distance