原文网址: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