先看效果图:

最直观的,这是4个圆点在移动,就用一个横向的StackPanel表示这四个点吧。

<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value=""/>
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl, AncestorLevel=1}, Path= Foreground}"/>
<Setter Property="CornerRadius" Value=""/>
<Setter Property="Height" Value=""/>
<Setter Property="Width" Value=""/>
</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 - ;
//正向加速度占比47.5%
double _0Width = realWidth * 0.475;
//匀速部分占比5%
double _1Width = _0Width + realWidth * 0.05; //根据控件的实际大小动态更改动画
#region 右边第一个
var _0 = storyboard.Children[] as DoubleAnimationUsingKeyFrames;
var _0_1 = _0.KeyFrames[] as EasingDoubleKeyFrame;
var _0_2 = _0.KeyFrames[] as EasingDoubleKeyFrame;
var _0_3 = _0.KeyFrames[] as EasingDoubleKeyFrame;
var _0_4 = _0.KeyFrames[] as EasingDoubleKeyFrame; _0_1.Value = _0Width;
_0_2.Value = _1Width;
_0_3.Value = realWidth;
_0_4.Value = realWidth;
#endregion #region 右边倒数第二个
var _1 = storyboard.Children[] as DoubleAnimationUsingKeyFrames;
var _1_1 = _1.KeyFrames[] as EasingDoubleKeyFrame;
var _1_2 = _1.KeyFrames[] as EasingDoubleKeyFrame;
var _1_3 = _1.KeyFrames[] as EasingDoubleKeyFrame;
var _1_4 = _1.KeyFrames[] as EasingDoubleKeyFrame; _1_1.Value = _0Width;
_1_2.Value = _1Width;
_1_3.Value = realWidth;
_1_4.Value = realWidth;
#endregion #region 右边倒数第三个
var _2 = storyboard.Children[] as DoubleAnimationUsingKeyFrames;
var _2_1 = _2.KeyFrames[] as EasingDoubleKeyFrame;
var _2_2 = _2.KeyFrames[] as EasingDoubleKeyFrame;
var _2_3 = _2.KeyFrames[] as EasingDoubleKeyFrame;
var _2_4 = _2.KeyFrames[] as EasingDoubleKeyFrame; _2_1.Value = _0Width;
_2_2.Value = _1Width;
_2_3.Value = realWidth;
_2_4.Value = realWidth;
#endregion #region 右边倒数第四个
var _3 = storyboard.Children[] as DoubleAnimationUsingKeyFrames;
var _3_1 = _3.KeyFrames[] as EasingDoubleKeyFrame;
var _3_2 = _3.KeyFrames[] as EasingDoubleKeyFrame;
var _3_3 = _3.KeyFrames[] as EasingDoubleKeyFrame;
var _3_4 = _3.KeyFrames[] 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

WPF:Metro样式ProgressBar(圆点横向移动),自适应宽度的更多相关文章

  1. ASP.NET实例——漂亮的自适应宽度的导航条(仿Discuz!)

    PHP比较成熟的开放的源代码比较多,比方说PrestaShop,比方说Discuz!...... 虽然语言不同,但基本原理是一样的,有时间的话读一读,对学习ASP.NET应该是非常有好处的(唉,什么时 ...

  2. shrink-to-fit(自适应宽度)

    自适应宽度是指当未明白设定容器的宽度(或外边距设为auto)时,在特定的情况下容器的宽度会依据情况自行设定.而设定的结果往往并非我们想要的. W3C规范中描写叙述了几种shrink-to-fit的情况 ...

  3. 从三栏自适应宽度布局到css布局的讨论

    如何实现一个三栏自适应布局,左右各100px,中间随着浏览器宽度自适应? 第一个想到的是使用table布局,设置table的宽度为100%,三个td,第1个和第3个固定宽度为100px,那么中间那个就 ...

  4. UEditor百度富文本编辑器--让编辑器自适应宽度的解决方案

    UEditor百度富文本编辑器的initialFrameWidth属性,默认值是1000. 不能够自适应屏幕宽度.如图1: 刚开始的时候,我是直接设置initialFrameWidth=null的.效 ...

  5. JS实现自适应宽度的Tag切换

    效果体验:http://hovertree.com/texiao/js/3.htm 该效果使用纯JavaScript代码,实现TAB页切换效果,TAB标签根据内容自适应宽度,点击TAB标签切换内容页. ...

  6. WPF设置DataGrid行内容高度自适应 与 TextBox/TextBlock内容高度自适应

    WPF设置DataGrid行内容高度自适应  TextBox/TextBlock内容高度自适应  参考: DataGrid 控件中的调整大小选项: http://msdn.microsoft.com/ ...

  7. RelativeLayout中的格局,自适应宽度布局

    RelativeLayout中的布局,自适应宽度布局 该图片中为android布局:总布局为 RelativeLayoutAtLeft 为居左 <TextView android:backgro ...

  8. Qt的tablewidget行列头自适应宽度

    Qt构造一个TableWidget后,窗口最大化后,列头默认不能自适应宽度,研究了一下,Qt提供了两种方式来处理这个问题,如下:   1. 使用horizontalHeader()->setRe ...

  9. [Winform]DataGridView列自适应宽度

    引言 在做winform项目中,数据控件DataGridView的使用多多少少是会用到的,如果不设置它的属性,默认情况下是不会自适应宽度的,你想查看某项的数据,就不得不将标题栏拖来拖去,挺烦的. 方法 ...

随机推荐

  1. 分布式事务之深入理解什么是2PC、3PC及TCC协议?

    导读 在上一篇文章<[分布式事务]基于RocketMQ搭建生产级消息集群?>中给大家介绍了基于RocketMQ如何搭建生产级消息集群.因为本系列文章最终的目的是介绍基于RocketMQ的事 ...

  2. js自定义对象和类

    1.工厂方式 <script type="text/javascript"> function createObject(name){        var p = n ...

  3. android WebView详解,常见漏洞详解和安全源码

    这篇博客主要来介绍 WebView 的相关使用方法,常见的几个漏洞,开发中可能遇到的坑和最后解决相应漏洞的源码,以及针对该源码的解析.  转载请注明出处:http://blog.csdn.net/se ...

  4. Java并发编程-再谈 AbstractQueuedSynchronizer 1 :独占模式

    关于AbstractQueuedSynchronizer JDK1.5之后引入了并发包java.util.concurrent,大大提高了Java程序的并发性能.关于java.util.concurr ...

  5. spring-boot(七) 随机端口

    学习文章:springboot小技巧 随机端口 为Spring Cloud的应用实用随机端口非常简单,主要有两种方法: 设置server.port=0,当应用启动的时候会自动的分配一个随机端口,但是该 ...

  6. 2.ES6引进的新特性——类Class

    为什么? ES6中引入了类,类在java/c++等面向对象的编程语言常见,JS引入类是为了在日后使用js开发大型的应用程序,类本质是语法糖(语法上更加人性化) 以前写一个类 function User ...

  7. [EOJ629] 两开花

    Description 给定一棵以 \(1\) 为根 \(n\) 个节点的树. 定义 \(f(k)\) :从树上等概率随机选出 \(k\) 个节点,这 \(k\) 个点的虚树大小的期望. 一个点 \( ...

  8. 第8章 CentOS包管理详解

    8.1 Linux上构建C程序的过程 在说明包相关的内容之前,我觉得有必要说一下在Linux上构建一个C程序的过程.我个人并没有学习过C,内容总结自网上,所以可能显得很小白,而且也并非一定正确,只希望 ...

  9. Perl匿名数组、hash和autovivification特性

    可有构建匿名的对象,这样就没必要去为只用一两次的数组.hash去取名字,有时候取名是很烦的事. 使用中括号[]构建匿名数组 使用大括号{}构建匿名hash 不包含任何元素的[]和{}分别是匿名空数组. ...

  10. python按引用赋值和深、浅拷贝

    按引用赋值而不是拷贝副本 在python中,无论是直接的变量赋值,还是参数传递,都是按照引用进行赋值的. 在计算机语言中,有两种赋值方式:按引用赋值.按值赋值.其中按引用赋值也常称为按指针传值(当然, ...