首页 > 其他分享 >WPF 自定义控件 动画仪表盘控件 Gauge

WPF 自定义控件 动画仪表盘控件 Gauge

时间:2022-11-06 20:24:17浏览次数:69  
标签:控件 自定义 double textBlock Gauge ArcGauge new line public

原文网址:https://blog.csdn.net/weixin_42850577/article/details/124008594

WPF 自制动画 仪表盘控件 Gauge

 

 

Xaml代码:

<Style TargetType="{x:Type ctrl:ArcGauge}">
<Setter Property="Background" Value="#646464"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ctrl:ArcGauge}">
<Border Margin="10">
<Grid Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}">
<Ellipse Fill="#FF3B3B3B"/>
<Grid RenderTransformOrigin="0.5,0.5" Margin="2">
<Grid.RenderTransform>
<TransformGroup>
<RotateTransform Angle="{Binding Path=Angle,ElementName=PointRotate}"/>
</TransformGroup>
</Grid.RenderTransform>
<Ellipse Width="16" Height="14" Fill="Orange" VerticalAlignment="Top" >
<Ellipse.Effect>
<BlurEffect Radius="12"/>
</Ellipse.Effect>
</Ellipse>
</Grid>

<Grid x:Name="bdGrid" Margin="12" UseLayoutRounding="True" ClipToBounds="True">
<Ellipse>
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="#4D000000"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="2*"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Ellipse Stroke="#464646" StrokeThickness="1" Grid.Column="1" Grid.Row="1"/>
<Ellipse Stroke="#959595" Margin="4" StrokeThickness="6" Grid.Column="1" Grid.Row="1"/>
<Ellipse Stroke="#464646" Margin="14" StrokeThickness="1" Grid.Column="1" Grid.Row="1"/>
</Grid>

<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Path Data="M5,0 5,0 10,120 0,120z" Fill="#0FA9CE" Stretch="Uniform" Margin="0 30 0 0" RenderTransformOrigin="0.5,1" HorizontalAlignment="Center">
<Path.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="PointRotate"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Grid>


<Ellipse Width="28" Height="28" Fill="Black">
<Ellipse.Effect>
<DropShadowEffect Color="#0FA9CE" ShadowDepth="0" Direction="0" BlurRadius="16"/>
</Ellipse.Effect>
</Ellipse>

<Border VerticalAlignment="Bottom" BorderBrush="#10ABD1" BorderThickness="2" Margin="0 0 0 12" Background="Black" Padding="8 2" HorizontalAlignment="Center">
<TextBlock Text="{Binding Value,RelativeSource={RelativeSource Mode=TemplatedParent}}" FontSize="16" Width="30" TextAlignment="Center" Foreground="White" FontWeight="Bold"/>
</Border>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

C#代码:

public class ArcGauge : Control
{
public ArcGauge()
{
Width = 200;
Height = 200;
SetCurrentValue(ValueProperty, 0d);
SetCurrentValue(MinValueProperty, 0d);
SetCurrentValue(MaxValueProperty, 100d);
}

private void InitTick()
{
// 画大刻度
for (int i = 0; i < 9; i++)
{
Line line = new Line();
line.X1 = 0;
line.Y1 = 0;
line.X2 = 0;
line.Y2 = 12;
line.Stroke = Brushes.White;
line.StrokeThickness = 2;
line.HorizontalAlignment = HorizontalAlignment.Center;
line.RenderTransformOrigin = new Point(0.5, 0.5);
line.RenderTransform = new RotateTransform() { Angle = -140 + i * 35 };
bdGrid.Children.Add(line);
DrawText();
}

// 画小刻度
for (int i = 0; i < 8; i++)
{
var start = -140 + 35 * i + 3.5;
for (int j = 0; j < 9; j++)
{
Line line = new Line();
line.X1 = 0;
line.Y1 = 0;
line.X2 = 0;
line.Y2 = 6;
line.Stroke = Brushes.White;
line.StrokeThickness = 1;
line.HorizontalAlignment = HorizontalAlignment.Center;
line.RenderTransformOrigin = new Point(0.5, 0.5);
line.RenderTransform = new RotateTransform() { Angle = start + j * 3.5 };
bdGrid.Children.Add(line);
}
}
}

List<TextBlock> textLabels = new List<TextBlock>();
private void DrawText()
{
foreach (var item in textLabels)
{
bdGrid.Children.Remove(item);
}
textLabels.Clear();

var per = MaxValue / 8;
for (int i = 0; i < 9; i++)
{
TextBlock textBlock = new TextBlock();
textBlock.Text = $"{MinValue + (per * i)}";
textBlock.HorizontalAlignment = HorizontalAlignment.Center;
textBlock.RenderTransformOrigin = new Point(0.5, 0.5);
textBlock.RenderTransform = new RotateTransform() { Angle = -140 + i * 35 };
textBlock.Margin = new Thickness(12);
textBlock.Foreground = Brushes.White;
bdGrid.Children.Add(textBlock);
textLabels.Add(textBlock);
}
}

static ArcGauge()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ArcGauge), new FrameworkPropertyMetadata(typeof(ArcGauge)));
}

RotateTransform rotateTransform;
Grid bdGrid;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
rotateTransform = GetTemplateChild("PointRotate") as RotateTransform;
bdGrid = GetTemplateChild("bdGrid") as Grid;
Refresh();
InitTick();
}

[Category("值设定")]
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(ArcGauge), new PropertyMetadata(0d, OnValueChanged));

private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => (d as ArcGauge)?.Refresh();

[Category("值设定")]
public double MinValue
{
get { return (double)GetValue(MinValueProperty); }
set { SetValue(MinValueProperty, value); }
}
public static readonly DependencyProperty MinValueProperty =
DependencyProperty.Register("MinValue", typeof(double), typeof(ArcGauge), new PropertyMetadata(0d, OnValueChanged));

[Category("值设定")]
public double MaxValue
{
get { return (double)GetValue(MaxValueProperty); }
set { SetValue(MaxValueProperty, value); }
}

public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(double), typeof(ArcGauge), new PropertyMetadata(0d, OnValueChanged));


private void Refresh()
{
if (rotateTransform == null)
return;
DoubleAnimation da = new DoubleAnimation();
da.Duration = new Duration(TimeSpan.FromMilliseconds(350));
da.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };

if (Value > MaxValue)
{
rotateTransform.Angle = 140;
da.To = 140;
}
else if (Value < MinValue)
{
rotateTransform.Angle = -140;
da.To = -140;
}
else
{
var range = MaxValue - MinValue;
var process = Value / range;
var tAngle = process * 280 - 140;
rotateTransform.Angle = tAngle;
da.To = tAngle;
}

rotateTransform.BeginAnimation(RotateTransform.AngleProperty, da);
}
}
————————————————
版权声明:本文为CSDN博主「不知名君」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42850577/article/details/124008594

标签:控件,自定义,double,textBlock,Gauge,ArcGauge,new,line,public
From: https://www.cnblogs.com/bruce1992/p/16863620.html

相关文章

  • 关于CHART控件使用的一个例子
    最近一段时间,有用到WinForm的chart控件,主要是做了一个纺织行业的验布数据的图表显示,比如长度值和重量值的曲线绘制,以此图表,相关人员则可判断哪些检验数据是错误......
  • 无废话zig系列 导入自定义api
    环境:ubuntu22.04zig0.10首先打开终端,建立zigexe项目:mkdirlibtestziginit-exe项目结构如下:├──build.zig└──src├──main.zig└......
  • C语言初级阶段6——自定义数据类型
    C语言初级阶段6——自定义数据类型阐述1.构造数据类型:用户自己建立的数据类型(自定义数据类型)。2.C语言中的自定义数据类型:数组类型、结构体类型、共用体类型和枚举类型......
  • springboot自定义starter集成controller、Dao
    springboot自定义starter集成controller、Dao编写starer,其他服务直接引入既可以,通常步骤为:pom中引入需要的依赖删除spring-boot-maven-plugin插件resources下新建spring.fac......
  • Android 自定义TextView实现文字和图片居中显示
    默认情况下,如果TextView的宽度超过文字的宽度,文字居中显示时,想要在文字的左边或者右边添加一个图片时,左边或者右边的文字就会默认以左边和右边开始排列,效果如下。如果想要......
  • PX01如何实现自定义循环老化画面、开关机冲击及自动关机
    屏在做实验室老化的时候,可能会需要对屏进行多种画面循环老化测试一定时间,完毕后自动关机下电;而循环画面要求也相对复杂,可能会有多种循环画面测试,而且每种循环次数不同,画面......
  • 自定义异常类
    1.继承现有异常结构,RuntimeException或者Exception2.提供全局常量:erialVersionUID 3.提供重载构造器4.在项目中即可调用throw MyException("不能。。。");publi......
  • ZYNQ & AXI总线 & PS与PL内部通信(用户自定义IP)
      ZYNQ、AXI协议、PS与PL内部通信 三种AXI总线分别为:AXI4:(Forhigh-performancememory-mappedrequirements.)主要面向高性能地址映射通信的需求,是面向地址映射的接......
  • React使用Antd自定义主题报错
    安装包"customize-cra":"^1.0.0","customize-cra-less-loader":"^2.0.0","less":"^4.1.3","less-loader":"^11.1.0",修改config-overrides.jsconst{override......
  • Thinkphp6笔记十九:加载自定义配置
    适用场景:加载自己的某些配置1.创建配置文件app/config/test.php或者app/admin/test.php<?phpreturn['rule'=>['alibaba'=>[],'ebay'=>[],......