之前看公司web前端做了個 圓形的水波紋 進度條,就想用wpf 做一個,奈何自己太菜 一直做不出來,在看過 “普通的地球人” 的 “ WPF實現三星手機充電界面 博客之後 我也來照葫蘆畫個瓢。 廢話不多說 先貼一下效果圖 雖然樣子 low 了些 但是基本滿足我的需求了,下麵是代碼 前端 後臺 美中不 ...
之前看公司web前端做了個 圓形的水波紋 進度條,就想用wpf 做一個,奈何自己太菜 一直做不出來,在看過 “普通的地球人” 的 “
WPF實現三星手機充電界面 博客之後 我也來照葫蘆畫個瓢。
廢話不多說 先貼一下效果圖
雖然樣子 low 了些 但是基本滿足我的需求了,下麵是代碼
前端
<UserControl x:Class="WaveProgress.UserControl.WaveProgressControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WaveProgress.UserControl" mc:Ignorable="d" Height="150" Width="150" x:Name="wave_control"> <UserControl.Resources> <Storyboard x:Key="WaterStoryboard"> <PointAnimation Storyboard.TargetName="bs_Water" DesiredFrameRate="20" Storyboard.TargetProperty="Point1" From="90,60" To="90,90" Duration="00:00:2" AutoReverse="True" RepeatBehavior="Forever"></PointAnimation> <PointAnimation Storyboard.TargetName="bs_Water" DesiredFrameRate="20" Storyboard.TargetProperty="Point2" From="100,110" To="100,95" Duration="00:00:1.8" AutoReverse="True" RepeatBehavior="Forever"></PointAnimation> </Storyboard> </UserControl.Resources> <Grid Width="{Binding ElementName=wave_control,Path=Width}" Height="{Binding ElementName=wave_control,Path=Height}" Background="{Binding WaveProgressBackground,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> <Grid.Clip> <EllipseGeometry Center="75,75" RadiusX="75" RadiusY="75" ></EllipseGeometry> </Grid.Clip> <StackPanel Width="150" VerticalAlignment="Bottom"> <Path Fill="{Binding WavePorgressBarColor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" > <Path.Data> <PathGeometry FillRule="EvenOdd" > <PathFigure StartPoint="0,90" > <BezierSegment x:Name="bs_Water" Point1="90,60" Point2="100,110" Point3="150,90"></BezierSegment> <PolyLineSegment Points="150,100 0,100"></PolyLineSegment> </PathFigure> </PathGeometry> </Path.Data> <Path.Triggers> <EventTrigger RoutedEvent="Path.Loaded"> <BeginStoryboard Storyboard="{StaticResource WaterStoryboard}"></BeginStoryboard> </EventTrigger> </Path.Triggers> </Path> <Rectangle Height="{Binding WaveProgressHeight,UpdateSourceTrigger=PropertyChanged}" Fill="{Binding WavePorgressBarColor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> </StackPanel> <Ellipse VerticalAlignment="Bottom" Width="150" Height="150" Stroke="{Binding WaveBorderBrush,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Fill="Transparent" StrokeThickness="{Binding WaveBorderThickness,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="22" Foreground="{Binding TextColor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> <Run Text="{Binding DisPlayValue,UpdateSourceTrigger=PropertyChanged}"></Run> <Run Text="%"></Run> </TextBlock> </Grid> </UserControl>
後臺
using System.Globalization; using System.Windows; using System.Windows.Media; namespace WaveProgress.UserControl { /// <summary> /// WaveProgressControl.xaml 的交互邏輯 /// </summary> public partial class WaveProgressControl : System.Windows.Controls.UserControl { public WaveProgressControl() { InitializeComponent(); this.DataContext = this; } public static readonly DependencyProperty WaveProgressBackgroundProperty = DependencyProperty.Register( "WaveProgressBackground", typeof(SolidColorBrush), typeof(WaveProgressControl), new PropertyMetadata(Brushes.White)); /// <summary> /// 進度條背景色 /// </summary> public SolidColorBrush WaveProgressBackground { get { return (SolidColorBrush) GetValue(WaveProgressBackgroundProperty); } set { SetValue(WaveProgressBackgroundProperty, value); } } public static readonly DependencyProperty WaveBorderBrushProperty = DependencyProperty.Register( "WaveBorderBrush", typeof(SolidColorBrush), typeof(WaveProgressControl), new PropertyMetadata(Brushes.Blue)); /// <summary> /// 邊框顏色 /// </summary> public SolidColorBrush WaveBorderBrush { get { return (SolidColorBrush) GetValue(WaveBorderBrushProperty); } set { SetValue(WaveBorderBrushProperty, value); } } public static readonly DependencyProperty WaveBorderThicknessProperty = DependencyProperty.Register( "WaveBorderThickness", typeof(double), typeof(WaveProgressControl), new PropertyMetadata(2.0)); /// <summary> /// 邊框粗細 /// </summary> public double WaveBorderThickness { get { return (double) GetValue(WaveBorderThicknessProperty); } set { SetValue(WaveBorderThicknessProperty, value); } } public static readonly DependencyProperty WavePorgressBarColorProperty = DependencyProperty.Register( "WavePorgressBarColor", typeof(SolidColorBrush), typeof(WaveProgressControl), new PropertyMetadata(Brushes.Red)); /// <summary> /// 進度條顏色 /// </summary> public SolidColorBrush WavePorgressBarColor { get { return (SolidColorBrush) GetValue(WavePorgressBarColorProperty); } set { SetValue(WavePorgressBarColorProperty, value); } } public static readonly DependencyProperty TextColorProperty = DependencyProperty.Register( "TextColor", typeof(SolidColorBrush), typeof(WaveProgressControl), new PropertyMetadata(Brushes.Black)); /// <summary> /// 文字顏色 /// </summary> public SolidColorBrush TextColor { get { return (SolidColorBrush) GetValue(TextColorProperty); } set { SetValue(TextColorProperty, value); } } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof(double), typeof(WaveProgressControl), new PropertyMetadata(default(double))); /// <summary> /// 當前進度 /// </summary> public double Value { get { return (double) GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register( "MaxValue", typeof(double), typeof(WaveProgressControl), new PropertyMetadata(default(double))); public double MaxValue { get { return (double) GetValue(MaxValueProperty); } set { SetValue(MaxValueProperty, value); } } public static readonly DependencyProperty DisPlayValueProperty = DependencyProperty.Register( "DisPlayValue", typeof(string), typeof(WaveProgressControl), new PropertyMetadata("0")); public string DisPlayValue { get { return (string) GetValue(DisPlayValueProperty); } set { SetValue(DisPlayValueProperty, value); } } public static readonly DependencyProperty WaveProgressHeightProperty = DependencyProperty.Register( "WaveProgressHeight", typeof(double), typeof(WaveProgressControl), new PropertyMetadata(default(double))); /// <summary> /// 次屬性不要手動設置 /// </summary> public double WaveProgressHeight { get { return (double) GetValue(WaveProgressHeightProperty); } set { SetValue(WaveProgressHeightProperty, value); } } protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { base.OnPropertyChanged(e); if (e.Property == ValueProperty) { double bl = Value / MaxValue; WaveProgressHeight = 140 * bl; DisPlayValue = (bl * 100).ToString(CultureInfo.InvariantCulture); } } } }
美中不足的是:
1、大小是我寫死了的,因為裡面那個水波是用path 寫的 是個固定的
2、仔細看 中間有條白色的線(等有時間在解決吧)
學習到的知識:
1、學會用貝塞爾曲線,和它的動畫
2、學會了Clip剪裁
3、看大佬的文章果然受益匪淺