当前位置:网站首页>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);
}
边栏推荐
- break algorithm---刷题map
- Coordinate conversion of one-dimensional array and two-dimensional matrix (storage of matrix)
- Usage of hydraulic rotary joint
- The solution of frame dropping problem in gnuradio OFDM operation
- qt--將程序打包--不要安裝qt-可以直接運行
- ROS problems (topic types do not match, topic datatype/md5sum not match, MSG XXX have changed. rerun cmake)
- COMSOL - Construction of micro resistance beam model - final temperature distribution and deformation - establishment of geometric model
- Plot function drawing of MATLAB
- Sum of submatrix
- About snake equation (2)
猜你喜欢
随机推荐
Leetcode exercise - Sword finger offer 36 Binary search tree and bidirectional linked list
MySQL数据库(2)
QT -- package the program -- don't install qt- you can run it directly
Why does the updated DNS record not take effect?
Redux使用
COMSOL----微阻梁模型的搭建---最终的温度分布和变形情况---材料的添加
MySQL查询为什么没走索引?这篇文章带你全面解析
Is it safe to open an account on your mobile phone for small amount of stock speculation?
Version 2.0 de tapdata, Open Source Live Data Platform est maintenant disponible
About snake equation (1)
Urban land use distribution data / urban functional zoning distribution data / urban POI points of interest / vegetation type distribution
COMSOL - Construction of micro resistance beam model - final temperature distribution and deformation - establishment of geometric model
Common operations of numpy on two-dimensional array
由排行榜实时更新想到的数状数值
【SolidWorks】修改工程图格式
Apache多个组件漏洞公开(CVE-2022-32533/CVE-2022-33980/CVE-2021-37839)
Problems of font legend and time scale display of MATLAB drawing coordinate axis
Codeforces Round #649 (Div. 2)——A. XXXXX
The function of carbon brush slip ring in generator
Matlab method is good~









