Silverlight 动画详解

时间:2022-12-30 12:11:54

Animation规则

基于时间:你设置动画的初始状态,最终状态,及持续时间,Silverlight会计算帧速率。

作用于属性(properties):一个Silverlight动画只能做一件事情,在某段时间内修改某个属性的值。这似乎是一个很大的限制,但你可以通过同时修改多个属性来创造令人惊讶的动画效果。

不同的数据类型需要不同的动画类。比如:Button.Width是double类型的,要创作针对这个属性的动画,你就要使用DoubleAnimation类。如果你想改变背景色,你就需要ColorAnimation 类。

Silverlight只有相当有限的几个Animation 类,你能修改的属性只限于以下几种类型:double, object,Color,Point.但是你也可以创建自己的animation类,用于不同的数据类型,你只需要继承System.Windows.Media.Animation,并指明值是如何随着时间改变的。

创建简单动画

创建一个简单的动画是多步骤的过程。你需要三个独立的成分:执行动画的对象,管理动画的故事板,和一个触发故事板的处理程序。

Animation Class

Silverlight有两种动画类,它们都用不同的策略来实现对值的改变。

线性插值:在动画期间,属性值连续不断的平衡变化。(你可以很容易的创建出包含加速与减速的复杂动作)。Silverlight包含三个这样的类:DoubleAnimation, PointAnimation, and ColorAnimation

关键帧动画:可以从一个值迅速转移到另一个值,或者他们可以结合跳跃和线性插值。Silverlight包含四个这样的类:

ColorAnimationUsingKeyFrames, DoubleAnimationUsingKeyFrames,
PointAnimationUsingKeyFrames, and ObjectAnimationUsingKeyFrames

动画是通过XAML语言来标记的。虽然动画类不是元素,但它们可以用相同的XAML语法来创建。例如,下面的标记创建了一个DoubleAnimation:

<DoubleAnimation From="160" To="300" Duration="0:0:5"></DoubleAnimation>

这个动画持续5秒(就如Duration属性指明的一样,它的格式是 Hours:Minutes:Seconds),动画运行时,它会把目标值从160平稳的改变到300。

然而,上面这段XAML丢失了一个重要的细节:我们并没有指明要改变的是哪个属性。这是我们所要说的另一个类--故事板所要做的工作。

The Storyboard Class

故事板管理动画的时间轴。你可以用故事板来分组多个动画,并对动画进行管理--暂停,停止,改变位置。但故事板最基本的特性是它提供了两个属性TargetProperty与TargetName来指明动画作用的属性与名称。换言之,故事板是动画与属性之间的桥梁。

这里说明如何定义一个故事板,通过DoubleAnimation 来改变名称为cmdGrow的button的Width属性。

<Storyboard x:Name="storyboard"
Storyboard.TargetName="cmdGrow" Storyboard.TargetProperty="Width">
<DoubleAnimation From="160" To="300" Duration="0:0:5"></DoubleAnimation>
</Storyboard>

Storyboard.TargetProperty表明了你想改变的属性(在这里是width)。如果你不指定一个类名,故事板会使用父元素。如果你想设置附加属性(例如,Canvas.Left or Canvas.Top),你需要用括号包起来:

<Storyboard x:Name="storyboard"
Storyboard.TargetName="cmdGrow" Storyboard.TargetProperty="(Canvas.Left)">
...
</Storyboard>

如果TargetProperty与TargetName都是附加属性,可以像下面那样指定:

<Storyboard x:Name="storyboard">
<DoubleAnimation
Storyboard.TargetName="cmdGrow" Storyboard.TargetProperty="Width"
From="160" To="300" Duration="0:0:5"></DoubleAnimation>
</Storyboard>

上面这种语法更常见,因为它允许你把几个动画放在相同的故事板,但每个动画设置不同的元素和属性。虽然你不能同时改变多个动画的同一个属性,但你可以(比较经常的)同时改变同一个对象的不同属性

Starting an Animation with an Event Trigger

定义一个故事板和动画对象是创建动画的第一步。要使故事板生效,你需要一个事件触发器。一个事件触发器响应故事板的执行事件。目前Silverlight通过BeginStoryboard来启动

故事板(包括它包含的动画)。

下面的例子使用页面的触发器集合附加一个加载动画事件。当Silverlight内容第一次呈现在浏览器中,且元素已加载完成,button就开始变形。5s之内,它的宽度由160变到300.

<UserControl ... >
<UserControl.Triggers>
<EventTrigger>
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="cmdGrow"
Storyboard.TargetProperty="Width"
From="160" To="300" Duration="0:0:5"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</UserControl.Triggers>
<Grid x:Name="LayoutRoot" Background="White">
<Button x:Name="cmdGrow" Width="160" Height="30"
Content="This button grows"></Button>
</Grid>
</UserControl>

不幸的是,相对于WPF事件,Silverlight有着及大的限制。Silverlight只支持页面第一次创建的时候触发Loaded事件。对于其它事件不能作出相应的响应,比如点击,按键和鼠标移动。

Starting an Animation with Code

在代码中,我们可以通过任意事件与故事板交互来启动Silverlight动画。我们要做的第一步,便是把故事板移到资源文件中。

<UserControl ... >
<UserControl.Resources>
<Storyboard x:Name="storyboard">
<DoubleAnimation
Storyboard.TargetName="cmdGrow" Storyboard.TargetProperty="Width"
From="160" To="300" Duration="0:0:5"></DoubleAnimation>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Button x:Name="cmdGrow" Width="160" Height="30" Click="cmdGrow_Click"
Content="This button grows"></Button>
</Grid>
</UserControl>

现在故事板有了一个名字,你可以在你的代码中操作它了。如:

private void cmdGrow_Click(object sender, RoutedEventArgs e)
{
storyboard.Begin();
}

单击按钮,启动动画,按钮的宽度会从160px拉伸到300px,如下图所示:

Silverlight 动画详解Silverlight 动画详解

Configuring Animation Properties

要深入了解Silverlight动画,你需要仔细看看那些看似简单的基本属性,包括From,To,Duration等。

FROM

From用来设置起始值。有前面的例子中,动画起始于160px.因些,每次你单击按钮启动动画,宽度会重置为160px,动画再次运行。即使你单击的时候,刚好有一个动画正在运行也是如此。(这也说明一个Silverlight动画细节:依赖属性只难存在于一个动画,当你开始第二个动画的时候,第一个动画便被丢弃)。

如果你在上面的例子中移除掉From属性,你可以多次单击按钮而不会将动画重置。每点一次,都开始一个新动画,在当前值开始变动。但是,当按钮到达最大值时,继续点击会变得无效,除非你让按钮回到原始值。

在上面的例子中,我们还可以设置ActualWidth属性,表示按钮的当前宽度。你不能用动画来改变它,因为它是只读的,但你可以用它来设置动画的起始位置。

TO

就如可以省略FROM属性一样,我们也可以省略TO属性。如:

<DoubleAnimation Storyboard.TargetName="cmdGrow"
Storyboard.TargetProperty="Width" Duration="0:0:5"></DoubleAnimation>

乍一看,这似乎什么都做不了,因为这既没有设置FROM属性与没有设置TO属性,他们都是相同的值。但这里有一个微妙且重要的区别。

当我们省略FROM时,Silverlight会将元素的当前值考虑到动画中,如前面例子中按钮的当前宽度。然而,当我们省略TO属性时,Silverlight豪不犹豫的使用当前值,即TO属性会变成最初的那个值。

BY

我们也可以使用BY属性,而不是TO。动画可以通过BY属性设置每一次的变化量,而不是最动画最终的值。比如,你可以通过BY属性,将当前宽度每次增加10PX.

<DoubleAnimation Storyboard.TargetName="cmdGrow" By="10"
Storyboard.TargetProperty="Width" Duration="0:0:5"></DoubleAnimation>

BY属性并不适合所有的非数值改变的动画类,比如ColorAnimation。

Duration

Duration表示动画从开始到结束之间的时间间隔。Duration属性的值要求是Duration类型的,类似TimeSpan。事实上,Duration类型可以隐匿的通过TimeSpan类型转换过来。

widthAnimation.Duration = TimeSpan.FromSeconds();

为什么微软要设置Duration类型,而不直接使用TimeSpan?因为Duration有两个特别的值是不能TimeSpan来表示的:Duration.Automatic与Duration.Forever。Duration.Automatic表示1s的持续时间,而Duration.Forever则表示永远的,这会让动画不产生任何影响。

Animation Lifetime

技术上来说Silverlight动画都是暂时的,这意味着它们不改变对象的基本特征。一旦启动了一个动画,它只是改覆盖了属性的当前值。因为这就是依赖属性的工作方式,这是一个很容易忽略的细节,并极易造成混乱。

一个单向动画(就像上面中按钮宽度的增长),当它完成运行后仍然是活动的。这是因为动画需要保持按钮宽度在新的尺寸。这会导致一个很常见的问题:当你在动画完成后,用代码修改属性的值,你的代码似乎没有任何影响。你的代码分配了一个新的本地值,但动画拥有较高的优先级。

对于这个问题,有下面几种解决方法:

1.创建一个动画,将你的元素设置城初始状态:这种方法不能设置TO属性。

2.创建一个可逆的动画:设置AutoReverse属性为true.

3.改变FillBehavior属性:通常,将FillBehavior属性设置HoldEnd,意味着动画结束时,目标属性就会回到原来的值。

4.动画结束时回收动画对象:在Completed事件中处理动画或故事板对象。

这里举一下第四种做法,在Completed将动画对象设置为原来的值:

private void storyboard_Completed(object sender, RoutedEventArgs e)
{
Storyboard storyboard = (Storyboard)sender;
storyboard.Stop();
double currentWidth = cmdGrow.Width;
storyboard.Stop();
cmdGrow.Width = currentWidth; }

RepeatBehavior

RepeatBehavior属性允许你控制动画的重复方式。如果你想指定一个重复次数,用数字表明次数,并紧跟着一个x。例如,下面指明这个动画重复两次:

<DoubleAnimation Storyboard.TargetName="cmdGrow" RepeatBehavior="2x"
Storyboard.TargetProperty="Width" To="300" Duration="0:0:5"></DoubleAnimation>

在后台代码中,可以这样写:

widthAnimation.RepeatBehavior = new RepeatBehavior();

除了可以设置重复次数外,你还可以设置动画的重复时间,在该段时间内,动画会一直重复执行。如:

<DoubleAnimation Storyboard.TargetName="cmdGrow" RepeatBehavior="0:0:13"
Storyboard.TargetProperty="Width" To="300" Duration="0:0:5"></DoubleAnimation>

对应的后台代码:

widthAnimation.RepeatBehavior = new RepeatBehavior(TimeSpan.FromSeconds());

除此之外,你还可以将RepeatBehavior的值设置成Forever,让动画一直不停的运行下去。

<DoubleAnimation Storyboard.TargetName="cmdGrow" RepeatBehavior="Forever"
Storyboard.TargetProperty="Width" To="300" Duration="0:0:5"></DoubleAnimation>

Simultaneous Animations

故事板有能力管理多个动画。最重要的是,将这些动画进行分组,就可以同时启动这些动画。

这里我们将两个动画放在同一个故事板中,一个动画作用于按钮的Width属性,另一个作用于Height属性。

    <Storyboard x:Name="storyboard2" Storyboard.TargetName="cmdGrow">
<DoubleAnimation Storyboard.TargetProperty="Width"
To="300" Duration="0:0:5"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="Height"
To="300" Duration="0:0:5"></DoubleAnimation>
</Storyboard>

有两个属于对多个动画时很有用,一个是BeginTime:控制动画的开始时间。一个是SpeedRatio:控制动画的变化速度。

Controlling Playback

Storyboard不单单有begin,end等方法,还有pause(暂停),resume(恢复),Seek(跳转)等方法。

例如:

Grid设置:

<Grid>
<Image Source="night.jpg"></Image>
<Image Source="day.jpg" x:Name="imgDay"></Image>
</Grid>

故事板设置:

<Storyboard x:Name="fadeStoryboard">
<DoubleAnimation x:Name="fadeAnimation"
Storyboard.TargetName="imgDay" Storyboard.TargetProperty="Opacity"
From="1" To="0" Duration="0:0:10">
</DoubleAnimation>
</Storyboard>

后台代码:

private void cmdStart_Click(object sender, RoutedEventArgs e)
{
fadeStoryboard.Begin();
}
private void cmdPause_Click(object sender, RoutedEventArgs e)
{
fadeStoryboard.Pause();
}
private void cmdResume_Click(object sender, RoutedEventArgs e)
{
fadeStoryboard.Resume();
}
private void cmdStop_Click(object sender, RoutedEventArgs e)
{
fadeStoryboard.Stop();
}
private void cmdMiddle_Click(object sender, RoutedEventArgs e)
{
// Start the animation, in case it's not currently underway.
fadeStoryboard.Begin();
// Move to the time position that represents the middle of the animation.
fadeStoryboard.Seek(
TimeSpan.FromSeconds(fadeAnimation.Duration.TimeSpan.TotalSeconds/));
}

private void sldSpeed_ValueChanged(object sender, RoutedEventArgs e)
{
// To nothing if the page is still being initialized.
if (sldSpeed == null) return;
// This also restarts the animation if it's currently underway.
fadeStoryboard.SpeedRatio = sldSpeed.Value;
lblSpeed.Text = sldSpeed.Value.ToString("0.0");
}

 

效果如图:

Silverlight 动画详解

Silverlight 动画详解的更多相关文章

  1. &lbrack;转&rsqb;Animation 动画详解(一)——alpha、scale、translate、rotate、set的xml属性及用法

    转载:http://blog.csdn.net/harvic880925/article/details/39996643 前言:这几天做客户回访,感触很大,用户只要是留反馈信息,总是一种恨铁不成钢的 ...

  2. &lbrack;转&rsqb; ReactNative Animated动画详解

    http://web.jobbole.com/84962/     首页 所有文章 JavaScript HTML5 CSS 基础技术 前端职场 工具资源 更多频道▼ - 导航条 - 首页 所有文章 ...

  3. &lbrack;转&rsqb;超级强大的SVG SMIL animation动画详解

    超级强大的SVG SMIL animation动画详解 本文花费精力惊人,具有先驱前瞻性,转载规则以及申明见文末,当心予以追究.本文地址:http://www.zhangxinxu.com/wordp ...

  4. Android中的动画详解系列【4】——Activity之间切换动画

    前面介绍了Android中的逐帧动画和补间动画,并实现了简单的自定义动画,这一篇我们来看看如何将Android中的动画运用到实际开发中的一个场景--Activity之间跳转动画. 一.定义动画资源 如 ...

  5. Android Animation动画详解(二): 组合动画特效

    前言 上一篇博客Android Animation动画详解(一): 补间动画 我已经为大家介绍了Android补间动画的四种形式,相信读过该博客的兄弟们一起都了解了.如果你还不了解,那点链接过去研读一 ...

  6. css 12-CSS3属性详解:动画详解

    12-CSS3属性详解:动画详解 #前言 本文主要内容: 过渡:transition 2D 转换 transform 3D 转换 transform 动画:animation #过渡:transiti ...

  7. Android 三种动画详解

    [工匠若水 http://blog.csdn.net/yanbober 转载请注明出处.点我开始Android技术交流] 1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让 ...

  8. 超级强大的SVG SMIL animation动画详解

    本文花费精力惊人,具有先驱前瞻性,转载规则以及申明见文末,当心予以追究.本文地址:http://www.zhangxinxu.com/wordpress/?p=4333 //zxx: 本文的SVG在有 ...

  9. css变换与动画详解

    举个栗子:--------元素整体居中.box{     position:absolute;top:50%;left:50%;    width:50px;    height:50px;    t ...

随机推荐

  1. IOS 中openGL使用教程3(openGL ES 入门篇 &vert; 纹理贴图(texture)使用)

    在这篇文章中,我们将学习如何在openGL中使用纹理贴图. penGL中纹理可以分为1D,2D和3D纹理,我们在绑定纹理对象的时候需要指定纹理的种类.由于本文将以一张图片为例,因此我们为我们的纹理对象 ...

  2. enum与typedef enum的用法

    一,两者的用法 枚举类型定义用关键字enum标识,形式为: enum 标识符 { 枚举数据表 }:枚举数据(枚举常量)是一些特定的标识符,标识符代表什么含义,完全由程序员决定.数据枚举的顺序规定了枚举 ...

  3. photosop快速对白色背景图片进行抠图

    因为其中有个作业,做个图书馆的小网页.所以打算取图书馆logo上面那几个字. 图片如下: 因为是白色背景,一开始打算使用魔棒工具,不过效果不好. 后来百度了下,使用色彩范围可以快速抠图 打开photo ...

  4. POJ3922 A simple stone game

    网上有很多解题报告,我的理解就是可以用类似数学归纳的方法证明,就是取一个数,让对手进入必败态. 详细见论文.

  5. &lbrack;js高手之路&rsqb;深入浅出webpack教程系列3-配置文件webpack&period;config&period;js详解&lpar;下&rpar;

    本文继续接着上文,继续写下webpack.config.js的其他配置用法. 一.把两个文件打包成一个,entry怎么配置? 在上文中的webpack.dev.config.js中,用数组配置entr ...

  6. Linux shell编程-退出的状态码

    linux 提供了一个专门的变量$?来保存上个已执行命令的状态码 linux 的错误状态退出状态码没有什么标准可遵循,但有一些参考 状态码 描述 0 命令成功结束 1 一般性未知错误 2 不适合的sh ...

  7. ffmpeg源码安装

    官网下载地址 http://www.ffmpeg.org/download.html https://sourceforge.net/projects/opencore-amr/ 参考资料:官网及以下 ...

  8. 开启或停止website

    1.添加:Microsoft.Web.Administration 2.代码: static void Main(string[] args) { var server = new ServerMan ...

  9. 全文搜索引擎 Elasticsearch 入门

    1. 百科 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作 ...

  10. How do I convert an IIR filter into a FIR filter in digital signal processing&quest;

    Maybe you were asking if there is some kind of design tool allowing to convert an IIR filter into an ...