WPF:Metro樣式ProgressBar(圓點橫向移動),自適應寬度


先看效果圖:

 

最直觀的,這是4個圓點在移動,就用一個橫向的StackPanel表示這四個點吧。

<StackPanel Orientation="Horizontal">
        <StackPanel.Resources>
            <Style TargetType="{x:Type Border}">
                <Setter Property="BorderBrush" Value="Transparent"/>
                <Setter Property="BorderThickness" Value="0"/>
                <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl, AncestorLevel=1}, Path= Foreground}"/>
                <Setter Property="CornerRadius" Value="100"/>
                <Setter Property="Height" Value="4"/>
                <Setter Property="Width" Value="4"/>
            </Style>
        </StackPanel.Resources>
        <Border x:Name="border4" Margin="0,0,5,0" RenderTransformOrigin="0.5,0.5">
            <Border.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </Border.RenderTransform>
        </Border>
        <Border x:Name="border3" Margin="0,0,5,0" RenderTransformOrigin="0.5,0.5">
            <Border.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </Border.RenderTransform>
        </Border>
        <Border x:Name="border2" Margin="0,0,5,0" RenderTransformOrigin="0.5,0.5">
            <Border.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </Border.RenderTransform>
        </Border>
        <Border x:Name="border1" RenderTransformOrigin="0.5,0.5">
            <Border.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </Border.RenderTransform>
        </Border>
    </StackPanel>

圓點的顏色綁定在用戶控件的Foreground上面。在調用控件的時候記得對其Foreground賦值以便顯示適合的顏色。

這個動畫實際上很簡單,分為5個部分:

1.准備部分:准備向前移動

2.正向加速度部分:移動速度越來越快

3.勻速部分:慢速勻速移動

4.負向加速度部分:移動速度越來越慢

5.等待部分:等待所有動畫完成

動畫代碼如下:

<Storyboard x:Key="sbKey" Completed="Storyboard_Completed"  >
            <!--最右邊-->
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="border1">
                <EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.8">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:1.2"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseIn"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:2.6"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="border2">
                <EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="0" x:Name="_2_1">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:0.9" Value="190" x:Name="_2_2">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:1.3" Value="210" x:Name="_2_3"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2.1" Value="400" x:Name="_2_4">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseIn"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:2.6" Value="400" x:Name="_2_5"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="border3">
                <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0" x:Name="_3_1">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="190" x:Name="_3_2">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="210" x:Name="_3_3"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2.2" Value="400" x:Name="_3_4">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseIn"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:2.6" Value="400" x:Name="_3_5"/>
            </DoubleAnimationUsingKeyFrames>
            <!--最左邊-->
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="border4">
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0" x:Name="_4_1">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:1.1" Value="190" x:Name="_4_2">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="210" x:Name="_4_3"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2.3" Value="400" x:Name="_4_4">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseIn"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                <EasingDoubleKeyFrame KeyTime="0:0:2.6" Value="400" x:Name="_4_5"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>

由於動畫需要自適應寬度,所以部分關鍵幀的值無法在XAML中表現出來,只有在后台進行動態處理。

當控件的寬度發生變化時需要更新動畫部分關鍵幀:

/// <summary>
        /// 當控件的大小發生變化時
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            //當控件的寬度發生變化時
            if(e.WidthChanged)
            {
                isNeedUpdateStoryboard = true;
            }
        }

當動畫每一次執行完畢后,下一次執行之前,判斷是否需要更新部分關鍵幀,所以響應動畫的Completed事件:

/// <summary>
        /// 動畫執行完畢
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Storyboard_Completed(object sender, EventArgs e)
        {
            //每次動畫執行完畢后判斷是否需要更新動畫
            if(isNeedUpdateStoryboard)
            {
                UpdateStoryboard();
            }

            isNeedUpdateStoryboard = false;
            storyboard.Begin(this);
        }
/// <summary>
        /// 更新動畫部分關鍵幀
        /// </summary>
        private void UpdateStoryboard()
        {
            //獲取控件的實際寬度,減去4個點占用的寬度
            double realWidth = this.ActualWidth - 36;
            //正向加速度占比47.5%
            double _0Width = realWidth * 0.475;
            //勻速部分占比5%
            double _1Width = _0Width + realWidth * 0.05;

            //根據控件的實際大小動態更改動畫
            #region 右邊第一個
            var _0 = storyboard.Children[0] as DoubleAnimationUsingKeyFrames;
            var _0_1 = _0.KeyFrames[1] as EasingDoubleKeyFrame;
            var _0_2 = _0.KeyFrames[2] as EasingDoubleKeyFrame;
            var _0_3 = _0.KeyFrames[3] as EasingDoubleKeyFrame;
            var _0_4 = _0.KeyFrames[4] as EasingDoubleKeyFrame;

            _0_1.Value = _0Width;
            _0_2.Value = _1Width;
            _0_3.Value = realWidth;
            _0_4.Value = realWidth;
            #endregion

            #region 右邊倒數第二個
            var _1 = storyboard.Children[1] as DoubleAnimationUsingKeyFrames;
            var _1_1 = _1.KeyFrames[1] as EasingDoubleKeyFrame;
            var _1_2 = _1.KeyFrames[2] as EasingDoubleKeyFrame;
            var _1_3 = _1.KeyFrames[3] as EasingDoubleKeyFrame;
            var _1_4 = _1.KeyFrames[4] as EasingDoubleKeyFrame;

            _1_1.Value = _0Width;
            _1_2.Value = _1Width;
            _1_3.Value = realWidth;
            _1_4.Value = realWidth;
            #endregion

            #region 右邊倒數第三個
            var _2 = storyboard.Children[2] as DoubleAnimationUsingKeyFrames;
            var _2_1 = _2.KeyFrames[1] as EasingDoubleKeyFrame;
            var _2_2 = _2.KeyFrames[2] as EasingDoubleKeyFrame;
            var _2_3 = _2.KeyFrames[3] as EasingDoubleKeyFrame;
            var _2_4 = _2.KeyFrames[4] as EasingDoubleKeyFrame;

            _2_1.Value = _0Width;
            _2_2.Value = _1Width;
            _2_3.Value = realWidth;
            _2_4.Value = realWidth;
            #endregion

            #region 右邊倒數第四個
            var _3 = storyboard.Children[3] as DoubleAnimationUsingKeyFrames;
            var _3_1 = _3.KeyFrames[1] as EasingDoubleKeyFrame;
            var _3_2 = _3.KeyFrames[2] as EasingDoubleKeyFrame;
            var _3_3 = _3.KeyFrames[3] as EasingDoubleKeyFrame;
            var _3_4 = _3.KeyFrames[4] as EasingDoubleKeyFrame;

            _3_1.Value = _0Width;
            _3_2.Value = _1Width;
            _3_3.Value = realWidth;
            _3_4.Value = realWidth;
            #endregion
        }

最后提供動畫的開始和結束調用:

/// <summary>
        /// 使進度條開始滾動
        /// </summary>
        public void Start()
        {
            this.Visibility = System.Windows.Visibility.Visible;
            UpdateStoryboard();
            storyboard.Begin(this, true);
        }
        /// <summary>
        /// 使進度條停止滾動
        /// </summary>
        public void Stop()
        {
            this.Visibility = System.Windows.Visibility.Collapsed;
            storyboard.Stop(this);
        }

源代碼下載:http://download.csdn.net/detail/lyclovezmy/7598897


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM