Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)

  正如你所看到的,Blend是一个非常强大的节约时间的设计工具,在Blend下能够设计出很多满意的动画作品,或许他具体是怎么实现的,通过什么方式实现的我们还是一无所知。本篇将续前面几篇基础动画之上,详细介绍Silverlight里提供故事板(StoryBorards)的属性和各种不同类型的动画(Animations)的详细知识点,揭晓在Blend下设计动画的内幕故事。

一、故事板(StoryBoard)属性

  Silvelight中的故事板(StoryBoard)提供了管理时间线的功能接口,可以用来控制一个或多个Silverlight动画进程,故我也称其为动画时间线容器。如下XAML代码块演示了通过StoryBoard来管理了名为GreenBall的元素在X坐标方向上的偏移变换动画。

<Storyboard x:Name="MoveBall">   
    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="GreenBall"          
               Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">         
            <EasingDoubleKeyFrame KeyTime="00:00:02" Value="540"/>     
  </DoubleAnimationUsingKeyFrames><
/Storyboard>

  StoryBoard提供了六个常用的动画属性选项,它们分别是:AutoReverse,BeginTime,Duration,FillBehavior,RepeatBehavior,SpeedRatio。通过这六个属性可以用来控制动画的基本行为动作,比如想要实现动画的缓冲时间,就需要用到Duration属性;设置动画的开始时间则用BeginTime;如果动画执行完后根据执行路线反向执行到原始状态则需要使用AutoReverse;如果需要设置动画的运行速度则使用SpeedRatio就可以完成。以下代码块演示了AutoReverse属性的使用,动画运行完后将按着原来的运行路线进行反向运行。更多详细可参考这篇博文介绍:《动画基础快速入门Animation》或者MSDN。

<Storyboard x:Name="MoveBall" AutoReverse="True">     
    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="GreenBall"          
      Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">        
     <EasingDoubleKeyFrame KeyTime="00:00:02" Value="540"/>     
</DoubleAnimationUsingKeyFrames></Storyboard>

  Storyboard的属性是可以组合应用的,如上代码块给动画设置了AutoReverse属性,使其在动画执行完后通过原来的运行路径进行回滚动画,可以给该动画时间线容器添加一个BeginTime属性,使其在程序加载后5秒钟才开始执行动画,这样就使用到了两个属性,如下代码块:

<Storyboard x:Name="MoveBall" AutoReverse="True" BeginTime="00:00:05">     ...... </Storyboard>

二、动画类型(Types of animation)

  Silverlight中的动画主要分From/To/By关键帧动画两种类型。

  From/To/By动画也称为线性插值动画(Linear Interpolation),是Silverlight类型中最简单的一种动画,只需要设置开始(From)、结束(To)和动画值(By)就可以完成动画的创建,Silverlight 3中提供了三种基础的From/To/By动画类型:DoubleAnimation、ColorAnimation和PointAnimation.

  关键帧动画比From/To/By动画更加强大,无需指定动画的开始、结束以及动画缓冲时间等相关参数,只需要关注关键帧和如何去控制动画就行了。Silverlight 3中提供了四种基本的关键帧动画:缓和(Easing)、线性(Linear)、样条(Spline)和离散(discreet)。

  DoubleAnimation的使用是非常简单的,只需要搞清楚From/To/By三要素就基本掌握了该类型动画的使用,下面是一个简单的通过DoubleAnimation实现的圆形移动的示例。


<UserControl x:Class="DoubleByAnimation.MainPage"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"      Width="800" Height="600">    
   <UserControl.Resources>         
      <Storyboard x:Name="Storyboard1">             
          <DoubleAnimation Storyboard.TargetName="Ellipse"                  
            Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"                  
            From="0"   By="150" Duration="00:00:01"/>         
      </Storyboard>     
  </UserControl.Resources>
    <Canvas x:Name="LayoutRoot" Background="White" >         
    <Ellipse Height="200" Width="200" Fill="#FFFF0000" Canvas.Top="181" Canvas.Left="92" RenderTransformOrigin="0.5,0.5" x:Name="Ellipse">             <Ellipse.RenderTransform>                 
          <TransformGroup>                     
            <ScaleTransform/>                     
              <SkewTransform/>                     
                <RotateTransform/>                     
            <TranslateTransform/>                 
          </TransformGroup>             
       </Ellipse.RenderTransform>         
    </Ellipse>     
  </Canvas>
</UserControl>

  下面通过一个稍复杂的示例来演示DoubleAnimation动画的使用,如下动画代码块实现了名称为Slider对象的X坐标方向的移动动画:


<Storyboard x:Name="SlideOut">     
    <DoubleAnimation Storyboard.TargetName="Slider"          
      Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"     
     Duration="00:00:00.50" To="150"/>
</Storyboard>
<Storyboard x:Name="SlideIn">    
   <DoubleAnimation Storyboard.TargetName="Slider"         
       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"      
    Duration="00:00:00.50" To="0"/>
</Storyboard>

  如上动画定义代码块中定义了两个动画,一个实现将对象Slider向X坐标方向移动到150像素点的位置,第二个动画实现将名为Silder的对象向X方向移动到0像素点的坐标位置,这样其实就实现了一个呈现与不呈现的效果。这里我们发挥大脑的潜力想象一下,如果Slider是一个面板对象,通过鼠标指向和离开的事件使用上面两个动画进行控制其不就实现了面板的鼠标指向就显示,离开就退回到原来的位置了?答案却是如此,详细见下代码块:


public partial class MainPage : UserControl
{     
    public MainPage()     
    {         
       InitializeComponent();
          Slider.MouseEnter += new MouseEventHandler(Slider_MouseEnter);         
        Slider.MouseLeave += new MouseEventHandler(Slider_MouseLeave);     
    }
    private void Slider_MouseLeave(object sender, MouseEventArgs e)     
   {         
      SlideIn.Begin();     
   }
    private void Slider_MouseEnter(object sender, MouseEventArgs e)    
   {         
    SlideOut.Begin();     
   }
}

        

  通过上面的示例,是否觉得要在Silverlight中实现一个动画是非常简单的?上面的示例就是掩饰了如何使用From/To/By的DoubleAnimation实现了对象的移动动画,同样也可以使用关键帧动画(DoubleUsingKeyframes)来实现这一功能。如下代码片段演示了元素Silder向X坐标方向移动到150像素点。


Storyboard MoveRight = new Storyboard();
DoubleAnimationUsingKeyFrames Anim = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTargetName(Anim, "Slider");
Anim.SetValue(Storyboard.TargetPropertyProperty,      
new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"));
Anim.BeginTime = new TimeSpan(, , );
SplineDoubleKeyFrame SKeyFrame = new SplineDoubleKeyFrame();
SKeyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5));
SKeyFrame.Value = ; Anim.KeyFrames.Add(SKeyFrame);
MoveRight.Children.Add(Anim);
......

  ColorAnimation类型动画主要应用于颜色上的变换动画效果,比如有一个圆,默认的填充颜色是红色(Red),设计一个动画通过2秒钟的动画换成将圆的填充颜色变换为蓝色。

<Ellipse Height="218" Width="218" Canvas.Left="294" Canvas.Top="195" Fill="#FFFF0000" Cursor="Hand" x:Name="RedEllipse"/>

  可以通过Blend的设计器来完成这样的动画的创建,在对象和时间轴面板里新建动画容器时间线,然后选中RadEllipse圆形对象在0秒的时间线上填充其颜色为红色,2秒的时间线上填充其颜色为蓝色,详细设计如下图:

        

  Blend最终生成的XAML代码如下:


<Storyboard x:Name="Storyboard1">     
    <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="RedEllipse"          
      Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">         
    <EasingColorKeyFrame KeyTime="00:00:00" Value="Red"/>         
     <EasingColorKeyFrame KeyTime="00:00:02" Value="Blue"/>     
    </ColorAnimationUsingKeyFrames>
</Storyboard>

  有Blend这样强大的设计工具是很幸运的,对于设计人员来说要实现一些动画需求直接通过界面设计就完成了。对于程序员来说就烦恼了,由于不熟悉设计工具,要实现某种动画只能通过编写程序代码来完成,这将是一个很庞大的工程,比如说当鼠标指向一圆的时候其填充颜色慢慢的向蓝色(Blue)渐变,鼠标离开的时候慢慢的恢复其默认颜色红色。实现这动画效果则需要写上如下长篇的程序代码:


private Storyboard TurnBlue = new Storyboard();
private Storyboard TurnRed = new Storyboard();
private ColorAnimation BlueColor = new ColorAnimation();
private ColorAnimation RedColor = new ColorAnimation();
public MainPage()
{     
   InitializeComponent();
     BlueColor.SetValue(Storyboard.TargetNameProperty, "RedEllipse");    
   BlueColor.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(Shape.Fill).(SolidColorBrush.Color)"));     
    BlueColor.To = Colors.Blue;     
    TurnBlue.Children.Add(BlueColor);     
    LayoutRoot.Resources.Add("TurnBlue", TurnBlue);
    RedColor.SetValue(Storyboard.TargetNameProperty, "RedEllipse");     
    RedColor.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(Shape.Fill).(SolidColorBrush.Color)"))     RedColor.To = Colors.Red;     TurnRed.Children.Add(RedColor);    
    LayoutRoot.Resources.Add("TurnRed", TurnRed);
    RedEllipse.MouseEnter += (senderRed, eRed) =>         
    {             
      TurnRed.Begin();         
   };    
    RedEllipse.MouseLeave += (senderBlue, eBlue) =>
   {             
      TurnBlue.Begin();         
   };
 
}

  这样的代码实现其实就是用程序代码创建了两个动画,一个由红色变换到蓝色,一个则由蓝色变换到红色,按照前面的方法直接在Blend中设计也是可以的。最终的运行效果如下图:

        

  PointAnimation类型动画更好理解,也就是动画效果是通过不同的坐标点来控制的。比如说浪涛的效果,下面就以浪涛为示例来演示PointAnimation类型动画的使用。

代码

<Storyboard x:Name="Storyboard1" RepeatBehavior="Forever" FillBehavior="HoldEnd">     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point2)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="351.732116699219,36.4064197540283"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="415.732116699219,84.4064178466797"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point3)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="425.502014160156,32.8349914550781"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="489.502014160156,80.8349914550781"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(BezierSegment.Point1)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="499.271911621094,29.2635669708252"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="563.271911621094,77.2635650634765"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point2)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="112.729011535644,80.834991455078"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="104.729011535645,32.8349914550781"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point3)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="185.502014160156,80.834991455078"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="177.502014160156,32.8349914550781"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point1)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="258.275024414062,80.834991455078"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="250.275024414063,32.8349914550781"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(BezierSegment.Point2)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="600.704162597656,72.7879943847655"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="608.704162597656,32.8349229097365"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(BezierSegment.Point3)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="665.502014160156,72.7879943847655"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="673.502014160156,32.8349229097365"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[3].(BezierSegment.Point1)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="730.299926757813,72.7879943847655"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="738.299926757813,32.8349229097365"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[3].(BezierSegment.Point2)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="801.502014160156,40.8349914550781"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="801.502014160156,56.8349229097366"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[3].(BezierSegment.Point3)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="801.502014160156,40.8349914550781"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="801.502014160156,56.8349229097366"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[4].(BezierSegment.Point1)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="801.502014160156,40.8349914550781"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="801.502014160156,56.8349229097366"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.StartPoint)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="1.50201416015619,32.834991455078"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="1.50201416015625,88.8349914550779"/>     </PointAnimationUsingKeyFrames>     <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="water" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point1)">         <EasingPointKeyFrame KeyTime="00:00:00" Value="1.50201416015619,32.834991455078"/>         <EasingPointKeyFrame KeyTime="00:00:03" Value="1.50201416015625,88.8349914550779"/>     </PointAnimationUsingKeyFrames></Storyboard>

        

  关于Silverlight中的动画相关的理论概论暂时就介绍这些,希望上面的简单介绍能帮助大家深入的理解和使用Blend进行各种不同的动画功能设计。更多信息可查阅下面的推资源连接。

故事板(StoryBoards)和动画(Animations)的更多相关文章

  1. Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)

    正如你所看到的,Blend是一个非常强大的节约时间的设计工具,在Blend下能够设计出很多满意的动画作品,或许他具体是怎么实现的,通过什么方式实现的我们还是一无所知.本篇将续前面几篇基础动画之上,详细 ...

  2. 【WPF学习】第五十七章 使用代码创建故事板

    在“[WPF学习]第五十章 故事板”中讨论了如何使用代码创建简单动画,以及如何使用XAML标记构建更复杂的故事板——具有多个动画以及播放控制功能.但有时采用更复杂的故事板例程,并在代码中实现全部复杂功 ...

  3. 【WPF学习】第五十章 故事板

    正如上一章介绍,WPF动画通过一组动画类(Animation类)表示.使用少数几个熟悉设置相关信息,如开始值.结束值以及持续时间.这显然使得它们非常适合于XAML.不是很清晰的时:如何为特定的事件和属 ...

  4. WPF动画——故事板(Storyboard)

    1.XAML代码 <Window x:Class="故事板.MainWindow" x:Name="window" xmlns="http:// ...

  5. iOS 5 故事板入门(3)

    原文: http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-2 Segues 介绍 是时候在我们的故事板中加入更 ...

  6. iOS 5 故事板入门(4)

    原文: http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-2 让 AddPlayer 窗口动起来 现在,我们先 ...

  7. Sliverlight之 故事板

    见Project19 (1) 将一张图片每隔一秒旋转72度,看看效果是什么样(使用定时器) 说明:前端 <Image.RenderTransform> <RotateTransfor ...

  8. iOS系列 基础篇 02 StoryBoard 故事板文件

    iOS基础 02 StoryBoard 故事板文件 目录: 1. 故事板的导航特点 2. 故事板中的Scene和Segue 3. 本文最后 在上篇HelloWorld工程中有一个Main.storyb ...

  9. [IOS 开发] TableView、多个TableViewCell、自定义Cell、Cell上画画(故事板+代码方式)

    第一步: //UserTableViewCell.h这里定义第一种Cell #import <UIKit/UIKit.h> @interface UserTableViewCell : U ...

随机推荐

  1. mysql —日志记录

    日志 事务日志: transaction log 中继日志: reley log错误日志: error log 通用日志: general log 慢查询日志: slow query log 二进制日 ...

  2. windows下使用eclipse远程编写hadoop配置

    1.按照一般方法配置好hadoop伪分布式,注意core-site.xml和mapred-site.xml用IP,不要用localhost 2.格式化hdfs文件系统hadoop namenode - ...

  3. Python - social-auth-app-django 模块 - 商城项目 第三方方式登录 - 微博

    开发准备 开通微博开发者权限 点击这里 进入 微博开放平台 开通后权限后创建应用 创建网页应用, 此处不需要进行审核即可使用测试环境 开发环境信息 此处一些信息是很重要的东西, 比如 App_key ...

  4. 阶段5 3.微服务项目【学成在线】_day04 页面静态化_14-页面静态化-数据模型-远程请求接口

    okhttp的官方文档: https://square.github.io/okhttp/ github的地址 https://github.com/square/okhttp/ 如何远程请求轮播图的 ...

  5. Qt编写安防视频监控系统9-自动隐藏光标

    一.前言 这个效果的灵感来自于大屏电子看板系统,在很多系统中尤其是上了大屏的时候,其实在用户不在操作的时候,是很不希望看到那个鼠标箭头指针的,只有当用户操作的时候才显示出来,这个就需要开个定时器定时计 ...

  6. Win10安装多个MySQL实例

    Win10安装MySQL-8.0.15 1.下载mysql-8.0.15-winx64.zip安装包,地址如下 https://cdn.mysql.com//Downloads/MySQL-8.0/m ...

  7. JAVA 基础编程练习题47 【程序 47 打印星号】

    47 [程序 47 打印星号] 题目:读取 7 个数(1—50)的整数值,每读取一个值,程序打印出该值个数的*. package cskaoyan; public class cskaoyan47 { ...

  8. JAVA 基础编程练习题25 【程序 25 求回文数】

    25 [程序 25 求回文数] 题目:一个 5 位数,判断它是不是回文数.即 12321 是回文数,个位与万位相同,十位与千位相同. package cskaoyan; public class cs ...

  9. 合并多个tensorflow模型的办法

    直接上代码: import tensorflow as tf from tensorflow.python.tools import freeze_graph from tensorflow.pyth ...

  10. jvm的内存结构和gc的回收

    推荐这篇文章,说的还比较完整,留个记号,以后方便查看 https://blog.csdn.net/m0_38110132/article/details/74542143