`
tianshibaijia
  • 浏览: 1127058 次
文章分类
社区版块
存档分类
最新评论

15.5.3 添加动画基元

 
阅读更多

15.5.3 添加动画基元

我们的目标是使构造动画的代码尽可能声明性和简单,为此,我们要提供专门为创建动画而设计的基元。我们已经看到,已经可以做需要的任何事情,只用现有的处理行为和绘图的函数,但是,如果我们可以使用专门的用于创建动画的基元,而不是显式使用提升,代码看起来会更优雅。让我们首先看一下处理绘图的函数。

创建用于动画的绘图基元

在清单 15.17 中,我们创建了 translate 基元,通过提升 Drawings.translate 函数处理动画。现在,我们需要做同样的事情,为其他绘图基元 circle 和 compose。清单 15.18 显示 F# 为创建一个动画的圆而声明的一个组合运算符和基元。还包括了组合的 C# 版本( 这次是作为扩展方法),来演示如何在 C# 中使用提升。其他提升操作的 C# 实现本质上是一样的,因此,没有包含在这个列表中。

Listing 15.18 Creating animation primitives using lifting in F# and C#

// F# version
> let circle brush size =
Behavior.lift2 Drawings.circle brush size
let ( -- ) anim1 anim2 =
Behavior.lift2 Drawings.compose anim1 anim2
;;
val circle : Behavior<#Brush> -> Behavior<float32> -> Behavior<Drawing>
val (--) : Behavior<#Drawing> -> Behavior<#Drawing> -> Behavior<Drawing>

// C# version
public static class Anims {
public static Behavior<IDrawing> Compose
(this Behavior<IDrawing> anim1, Behavior<IDrawing> anim2) {
return Behavior.Lift<IDrawing, IDrawing, IDrawing>
(Drawings.Compose)(anim1, anim2);
}
}

在 F# 中使用提升是很容易的,由于其先进的类型推断。我们早些时候创建了 translate 基元,因此,在这个清单中,只添加了 circle 函数和一个自定义操作符,用于组合动画。它们都有两个参数,所以,可以使用 Behavior.lift2 函数,一个参数是处理的函数,另一个是把它转换成处理动画的变量。正如你从推导出的类型签名看到的,函数 (或运算符)的结果,是取两个行为作为参数,返回一个行为(更具体地说,是 Behavior<Drawing>,表示动画)。函数 circle 现在取画笔和大小都作为行为,因此,我们可以创建随时间改变颜色和大小的圆。

在 C# 版本中,我们为所有操作创建静态的 Anims 类。第 6 章中,我们比较过 C# 中的扩展方法和 F# 中的自定义运算符,建议应把 Compose 实现为扩展方法。在方法体中,使用提升,获得 Drawings.Compose 方法的提升版本。Lift 方法返回一个我们立即调用的函数,我们给它两个动画作为参数,并返回组合了的动画结果。在讨论如何使用新功能之前,做两个改进,让我们能够用行为做更有趣的事。

用行为计算

我们频繁使用的另一个操作,是为行为乘以或加上一个数字。在示例动画中,我们想为 wiggle 值乘以常量行为 100.0f.forever。没有显式使用提升,而是提供重载运算符,处理数字的行为,更加方便。清单 15.19 显示如何在 F# 中实现加法和乘法两个运算符。

Listing 15.19 Extension operators for calculating with behaviors (F#)

type Behavior<'T> with
static member (+) (a:Behavior<float32>, b) =
Behavior.lift2 (+) a b
static member (*) (a:Behavior<float32>, b) =
Behavior.lift2 (*) a b

在 F# 中,我们可以使用固有的类型扩展,为类型添加运算符。将为类型添加两个静态成员,每个成员都取两个类型为 Behavior<float32> 的参数。添加处理任何数值类型的泛型运算符,将更加困难,所以,我们在这一章中,只创建处理数值类型的运算符。运算符的实现很容易,因为,我们可以用适当的提升函数来表达。C# 的实现是几乎完全相同,所以,我们不谈论它。

我们已经把加法和乘法概念应用到位置,但是,我们的动画处理的其他维度是时间,我们可以做什么呢?好吧,我们可能要加快动画,或延迟一段时间。如果我们有两个旋转的圆,可能要使一个旋转的比另一个快两倍。我们可以创建一个新的基元行为,但是,有一种更优雅的方法,可以创建一个函数,取一个行为作为参数,并返回一个新的行为,它运行得更快,或延迟了指定的秒数。你可以在清单 15.20 中看到 F# 的版本。

Listing 15.20 Speeding up and delaying behaviors (F#)

let wait shift (BehaviorFunc bfunc) =
sample(fun t -> bfunc { t with Time = t.Time + shift })
let faster q (BehaviorFunc bfunc) =
sample(fun t -> bfunc { t with Time = t.Time * q })

清单 15.20 中的函数使用可以处理任何一种行为,而不仅仅是动画。每个函数取一个浮点数作为第一个参数,原始的行为作为第二个参数。为了创建一个新的行为,我们必须使用低级的 sample 基元。我们创建一个新的行为,它调用从原始行为中提取的函数,并把不同的时间给它作为参数。在第一种情况下,时间被推移了指定的秒数,第二种情况中,它乘上了提供的系数。为了解释其含义,让我们看一下第二个函数,假设我们将以两倍的速度运行一个行为。当实际时间为 3 秒,所返回的行为将用 6 秒的时间调用原来的行为,这意味着,动画做的动作,通常会执行 6 秒,只需 3 秒。

我们可以写一个完全通用的函数,用于操作时间。更一般的版本会用行为调整时间,即,取原始时间,返回调整的时间的函数。我们已经创建的 simple 函数的使用和理解将容易。

在最后的演示中,我们将创建太阳、月亮和地球的动画。它将使用我们迄今实现的所有功能,来创建一个复杂、有趣的动画,用它来演示如何组合和可重用解决方案。

分享到:
评论

相关推荐

    TeamViewer-15.5.3.rar

    远程电脑工具,可以传输文件

    teamviewer_15.5.3_amd64.deb

    TeamViewer是一个在任何防火墙和NAT代理的后台用于远程控制,桌面共享和文件传输的简单且快速的解决方案(非开源软件)。为了连接到另一台计算机,只需要在 两台计算机上同时运行 TeamViewer 即可而不需要进行一个...

    qt5-qtwebkit-5.212.20200324-1-omv4002.x86_64.rpm

    成功安装Teamviewer的关键,解决:缺少libQt5WebKitWidgets.so的关键包。 以下是错误原文 --&gt; 解决依赖关系完成 ... 您可以尝试添加 --skip-broken 选项来解决该问题 您可以尝试执行:rpm -Va --nofiles --nodigest

    网页与Web程序设计 课件 ppt 机械工业出版社 part1

    第三部分为图形动画篇(第12~15章),介绍目前最常用的网页制作辅助工具Fireworks 8和Flash 8,并给出一些制作实例。  网页设计是一门实践性很强的课程,实践是学好本课程的重要环节。为此我们编写了与其配套的...

    eamViewer(远程连接控制

    eamViewer(远程连接控制eamViewer(远程连接控制

    gitlab-ce-13.5.3-ce.0.el7.x86_64.rpm

    gitlab

    ASP.NET 2.0+SQL Server 2005全程指南-源代码

    15.5.3 添加照片 15.5.4 编辑和删除照片 15.6 本章小结 第16章 办公自动化系统 16.1 系统总体设计 16.1.1 系统功能描述 16.1.2 系统架构设计 16.2 系统模块设计 16.2.1 系统功能模块划分 16.2.2 功能模块...

    一款非常好的WPF编程宝典2010 源代码

    15.5.3 修改滚动条 390 15.5.4 创建自定义窗口 394 15.5.5 SimpleStyle示例项目 398 15.6 结束语 400 第16章 数据绑定 401 16.1 数据绑定基础 401 16.1.1 绑定到元素的属性 401 16.1.2 使用代码创建绑定 404 ...

    Apress.Pro.WPF.in.C.Sharp.2008.2nd.Edition.Feb.2008

    15.5.3 修改滚动条 390 15.5.4 创建自定义窗口 394 15.5.5 SimpleStyle示例项目 398 15.6 结束语 400 第16章 数据绑定 401 16.1 数据绑定基础 401 16.1.1 绑定到元素的属性 401 16.1.2 使用代码创建绑定 404 16.1.3 ...

    《零基础学ASP.NET 2.0》第15章 数据绑定控件显示数据

    15.1 GridView控件 266 15.1.1 绑定数据到GridView控件 266 15.1.2 数据排序并进行分页 267 15.1.3 数据编辑和删除 269 15.2 DetailsView控件 272 ...15.5.3 如何在用GridView控件浏览数据时插入新数据 284

    ASP.NET2.0高级编程(第4版)1/6

     20.5.1 给页面添加多个表702  20.5.2 给SQL Server 高速缓存依赖性和 Request对象建立关联702  20.5.3 给SQL Server 高速缓存依赖性 和Cache对象建立关联703 20.6 小结706 第21章 调试和错误处理技术709 21.1 ...

    Visual C++ 2010入门经典(第5版)--源代码及课后练习答案

    CruiseYoung提供的带有详细书签的电子书籍目录 ... 该资料是《Visual C++ 2010入门经典(第5版)》的源代码及课后练习答案 对应的书籍资料见: Visual C++ 2010入门经典(第5版) ...原书名: Ivor Horton's Beginning ...

    AspNet MVC 开发技术

    15.5.3 CheCkbox控件的属性 408 15.5.4 CheCkbox控件的事件 409 15.5.5 groupbox控件 409 15.6 riChtextbox控件 412 15.6.1 riChtextbox控件的属性 412 15.6.2 riChtextbox控件的事件 413 15.7 listbox和...

    Eclipse权威开发指南3.pdf

    6.5.1 安装位置的添加和删除..... 171 6.5.2 功能部件的禁用和启用..... 171 6.5.3 从更新站点安装功能部件..... 172 6.5.4 将服务应用于功能部件..... 173 6.5.5 相关练习..... 173 6.6 配置的管理...

    Eclipse权威开发指南1.pdf

    6.5.1 安装位置的添加和删除..... 171 6.5.2 功能部件的禁用和启用..... 171 6.5.3 从更新站点安装功能部件..... 172 6.5.4 将服务应用于功能部件..... 173 6.5.5 相关练习..... 173 6.6 配置的管理...

    Eclipse权威开发指南2.pdf

    6.5.1 安装位置的添加和删除..... 171 6.5.2 功能部件的禁用和启用..... 171 6.5.3 从更新站点安装功能部件..... 172 6.5.4 将服务应用于功能部件..... 173 6.5.5 相关练习..... 173 6.6 配置的管理...... 174 ...

    精通MFC (光盘) 源代码

    15.5.3 m_xDispatch成员 15.5.4 输出IDispatch接口 15.5.5 双重接口的客户端 15.5.6 范例 15.6 可连接对象及其MFC实现 15.6.1 用CCmdTarget实现可连接对象 15.6.2 可连接对象的客户端 15.7 封送的应用:在...

    Ext Js权威指南(.zip.001

    8.3.7 为组件实现动画功能:ext.util.animate / 422 8.3.8 其他的组件辅助功能类 / 423 8.4 组件的管理 / 423 8.4.1 组件管理及查询:ext.componentmanager与ext.componentquery / 423 8.4.2 焦点管理:ext....

Global site tag (gtag.js) - Google Analytics