当前位置:网站首页>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);
}
边栏推荐
- regular expression
- Break algorithm --- map
- node js 保持长连接
- Codeforces Round #633 (Div. 2) B. Sorted Adjacent Differences
- [target tracking] |dimp: learning discriminative model prediction for tracking
- cv2读取视频-并保存图像或视频
- mysql/mariadb怎样生成core文件
- Mouse event - event object
- Codeforces Round #643 (Div. 2)——B. Young Explorers
- 如果时间是条河
猜你喜欢

如何让导电滑环信号更好

微信小程序uniapp页面无法跳转:“navigateTo:fail can not navigateTo a tabbar page“

Urban land use distribution data / urban functional zoning distribution data / urban POI points of interest / vegetation type distribution

《ClickHouse原理解析与应用实践》读书笔记(7)

ANSI / NEMA- MW- 1000-2020 磁铁线标准。. 最新原版

Js中forEach map无法跳出循环问题以及forEach会不会修改原数组

Introduction to grpc for cloud native application development

快速熟知XML解析

第七章 行为级建模

The foreach map in JS cannot jump out of the loop problem and whether foreach will modify the original array
随机推荐
用户之声 | 对于GBase 8a数据库学习的感悟
Matlab method is good~
Usage of xcolor color in latex
Nmap tool introduction and common commands
Redission源码解析
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
滑环在直驱电机转子的应用领域
uniapp一键复制功能效果demo(整理)
adb工具介绍
Codeforces Round #649 (Div. 2)——A. XXXXX
Qml 字体使用pixelSize来自适应界面
The method of using thread in PowerBuilder
Anaconda3 tutorial on installing and adding Tsinghua image files
[error] error loading H5 weight attributeerror: 'STR' object has no attribute 'decode‘
Partage d'expériences de contribution à distance
Qt - - Packaging Programs - - Don't install Qt - can run directly
Application of slip ring in direct drive motor rotor
From starfish OS' continued deflationary consumption of SFO, the value of SFO in the long run
如何制作企业招聘二维码?
Remote Sensing投稿经验分享