直接上图,先看效果
代码
public partial class MeterPlate : UserControl
{
public MeterPlate()
{
InitializeComponent();
Loaded += MeterPlate_Loaded;
}
private static double StartAngle = -135.5;
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(MeterPlate),
new PropertyMetadata(default(double), new PropertyChangedCallback(OnValuePropertyChanged)));
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(MeterPlate),
new PropertyMetadata(double.NaN, new PropertyChangedCallback(OnPropertyChanged)));
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(MeterPlate),
new PropertyMetadata(double.NaN, new PropertyChangedCallback(OnPropertyChanged)));
public Brush PlateBackground
{
get { return (Brush)GetValue(PlateBackgroundProperty); }
set { SetValue(PlateBackgroundProperty, value); }
}
public static readonly DependencyProperty PlateBackgroundProperty =
DependencyProperty.Register("PlateBackground", typeof(Brush), typeof(MeterPlate), null);
public Brush PlateBorderBrush
{
get { return (Brush)GetValue(PlateBorderBrushProperty); }
set { SetValue(PlateBorderBrushProperty, value); }
}
public static readonly DependencyProperty PlateBorderBrushProperty =
DependencyProperty.Register("PlateBorderBrush", typeof(Brush), typeof(MeterPlate), null);
public Thickness PlateBorderThickness
{
get { return (Thickness)GetValue(PlateBorderThicknessProperty); }
set { SetValue(PlateBorderThicknessProperty, value); }
}
public static readonly DependencyProperty PlateBorderThicknessProperty =
DependencyProperty.Register("PlateBorderThickness", typeof(Thickness), typeof(MeterPlate), null);
public static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as MeterPlate).DrawScale();
}
public static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MeterPlate dashboard = d as MeterPlate;
dashboard.DrawAngle();
//double step = 270.0 / (dashboard.Maximum - dashboard.Minimum);
//DoubleAnimation da = new DoubleAnimation(dashboard.Value * step - 45, new Duration(TimeSpan.FromMilliseconds(200)));
//dashboard.rtPointer.BeginAnimation(RotateTransform.AngleProperty, da);
dashboard.arckd.EndAngle = StartAngle + (-StartAngle * 2d) * ((double)dashboard.Value / dashboard.Maximum);
dashboard.valueTxt.Text = dashboard.Value.ToString();
}
private void MeterPlate_Loaded(object sender, RoutedEventArgs e)
{
this.DrawScale();
}
/// <summary>
/// 画表盘的刻度
/// </summary>
private void DrawScale()
{
this.canvasPlate.Children.Clear();
for (double i = 0; i <= this.Maximum - this.Minimum; i++)
{
//添加刻度线
Line lineScale = new Line();
if (i % 10 == 0)
{
//注意Math.Cos和Math.Sin的参数是弧度,记得将角度转为弧度制
lineScale.X1 = 200 - 170 * Math.Cos(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Y1 = 200 - 170 * Math.Sin(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Stroke = new SolidColorBrush(Colors.White);
lineScale.StrokeThickness = 2;
//添加刻度值
TextBlock txtScale = new TextBlock();
txtScale.Text = (i + this.Minimum).ToString();
txtScale.Width = 34;
txtScale.TextAlignment = TextAlignment.Center;
txtScale.Foreground = new SolidColorBrush(Colors.White);
txtScale.RenderTransform = new RotateTransform() { Angle = 45, CenterX = 17, CenterY = 8 };
txtScale.FontSize = 18;
Canvas.SetLeft(txtScale, 200 - 155 * Math.Cos(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180) - 17);
Canvas.SetTop(txtScale, 200 - 155 * Math.Sin(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180) - 10);
this.canvasPlate.Children.Add(txtScale);
}
else
{
lineScale.X1 = 200 - 180 * Math.Cos(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Y1 = 200 - 180 * Math.Sin(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Stroke = new SolidColorBrush(Colors.White);
lineScale.StrokeThickness = 1;
lineScale.Opacity = 0.5;
}
lineScale.X2 = 200 - 190 * Math.Cos(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Y2 = 200 - 190 * Math.Sin(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
this.canvasPlate.Children.Add(lineScale);
}
}
private void DrawAngle()
{
double step = 270.0 / (this.Maximum - this.Minimum);
DoubleAnimation da = new DoubleAnimation(this.Value * step - 45, new Duration(TimeSpan.FromMilliseconds(200)));
this.rtPointer.BeginAnimation(RotateTransform.AngleProperty, da);
}
}
界面代码
<UserControl.Resources>
<ResourceDictionary Source="pack://application:,,,/WINOWE.Control;component/BaseStyle.xaml" />
</UserControl.Resources>
<Grid>
<Viewbox>
<Border CornerRadius="200" ClipToBounds="True"
BorderBrush="{Binding PlateBorderBrush ,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor}}"
BorderThickness="{Binding PlateBorderThickness,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor}}"
Background="{Binding PlateBackground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}">
<Grid>
<Border>
</Border>
<Canvas Name="canvasPlate" Width="400" Height="400" Background="Transparent" Margin="14">
<Canvas.RenderTransform>
<RotateTransform Angle="-45" CenterX="200" CenterY="200"/>
</Canvas.RenderTransform>
</Canvas>
<ed:Arc ArcThickness="24" Opacity="0.1"
ArcThicknessUnit="Pixel"
EndAngle="135.5"
Fill="{DynamicResource ColorBrush}"
StartAngle="-135.5"
Stretch="None"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round" />
<ed:Arc ArcThickness="24" Opacity="0.8" x:Name="arckd"
Fill="{DynamicResource ColorBrush1}"
ArcThicknessUnit="Pixel"
EndAngle="50"
StartAngle="-135.5"
Stretch="None"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round" >
<!--<ed:Arc.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.1" Color="Transparent"/>
<GradientStop Offset="0.5" Color="{DynamicResource ColorLight}"/>
<GradientStop Offset="1" Color="{DynamicResource ColorLight1}"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</ed:Arc.Fill>-->
</ed:Arc>
<!--<Path Data="M100 200 A100 100 0 1 1 200 300" Stroke="#4169E1" Opacity="0.7" StrokeThickness="10" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.RenderTransform>
<RotateTransform Angle="-45" CenterX="200" CenterY="200"/>
</Path.RenderTransform>
</Path>-->
<!-- 刻度盘当前值对应的圆弧 -->
<Border Width="240" Height="240" CornerRadius="120" Opacity="0.5" Margin="14">
<Border.Background>
<RadialGradientBrush RadiusX="1" RadiusY="1">
<GradientStop Color="{DynamicResource ColorLight2}" Offset="0.2"/>
<GradientStop Color="{DynamicResource ColorLight1}" Offset="0.3"/>
<GradientStop Color="{DynamicResource ColorLight}" Offset="0.5"/>
</RadialGradientBrush>
</Border.Background>
</Border>
<Path Name="pointer" Data="M200 205,40 200,200 195,200 205" RenderTransformOrigin="0.5,0.5" Margin="14">
<Path.Fill>
<RadialGradientBrush RadiusX="1" RadiusY="1">
<GradientStop Color="{DynamicResource LightBlueColor1}" Offset="0.3"/>
<GradientStop Color="{DynamicResource LightBlueColor2}" Offset="0.4"/>
<GradientStop Color="{DynamicResource LightBlueColor3}" Offset="1"/>
</RadialGradientBrush>
</Path.Fill>
<Path.RenderTransform>
<RotateTransform x:Name="rtPointer" Angle="-45"/>
</Path.RenderTransform>
</Path>
<Border Width="80" Height="80" CornerRadius="40" Margin="14">
<Border.Background>
<RadialGradientBrush RadiusX="1" RadiusY="1">
<GradientStop Color="{DynamicResource ColorLight2}" Offset="0.2"/>
<GradientStop Color="{DynamicResource ColorLight1}" Offset="0.3"/>
<GradientStop Color="{DynamicResource ColorLight}" Offset="0.5"/>
</RadialGradientBrush>
</Border.Background>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock x:Name="valueTxt" FontSize="30" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="km/h" FontSize="12" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
</Grid>
</Border>
</Viewbox>
</Grid>
用法
<dashboard:MeterPlate Name="meterPlate" Maximum="180" Minimum="0" Value="150" Margin="20"/>
gitee源代码下载:https://gitee.com/lm961031/wpf.-dashboard
csdn源代码下载:https://download.csdn.net/download/qq_42707143/87719177?spm=1001.2014.3001.5503