搜索
首页web前端html教程iOS UIView动画实践(五):Keyframe Animation_html/css_WEB-ITnose

前言

有些时候大家可能会遇到制作复杂、具有连贯性UIView动画的需求,这时大家可能会使用在completion闭包中衔接一段一段的动画,使之成为一段连续的动画。

如果我们只是连接2个,或者3个动画,这种方式或许还行得通,但如果有更多的动画片段需要连接的时候,这种方式会带来灾难性的问题,你的代码会非常的冗余,不断的在completion闭包中嵌套代码,使代码维护起来相当的困难。所以今天向大家介绍能更好地实现这个需求的方法,Keyframe动画。

Keyframe动画可以让我们有效的拆分由若干段动画连接而成的复杂动画,可以较为精准的定义每段动画的起始点及持续时间,并且在代码组织方面也非常清晰。先看看今天要带大家实现的动画Demo:

           

使用场景

我们先来认识一下,在什么样的场景下需要使用Keyframe动画。如图下所示,这是一个由四段动画组成的一个复杂动画,让UIView沿着长方形的轨迹运动:

我们来看看用代码如何实现:

[cpp] view plaincopy

  1. UIView.animateWithDuration(1, animations: {  

  2.     view.center.x += 200.0  

  3. }, completion: { _ in  

  4.     UIView.animateWithDuration(1, animations: {  

  5.         view.center.y += 100.0  

  6.     }, completion: { _ in  

  7.         UIView.animateWithDuration(1, animations: {  

  8.             view.center.x -= 200.0  

  9.         }, completion: { _ in  

  10.             UIView.animateWithDuration(1, animations: {  

  11.                 view.center.y -= 100.0  

  12.             }, completion: nil)  

  13.         })  

  14.     })  

  15. })  

通过上面的伪代码可以看到,我们使用了completion闭包的方式连接每一段的动画,代码看起来尚且算清晰,可读性也马马虎虎。但是大家想象一下,如果我们使UIView按照一个复杂的路线运行,这一段动画可能有十几、几十段动画组成的,那么如果再使用completion闭包这种方式连接,那代码是多么的惨不忍睹。幸好我们有Keyframe动画,下面就让我们来看看如何使用Keyframe动画。

Keyframe动画

首先我们会使用到UIView的另一个动画方法animateKeyframesWithDuration(_: delay: options: animations: completion: ) :

[cpp] view plaincopy

  1. UIView.animateKeyframesWithDuration(2, delay: 0, options: [], animations: {  

  2.     // add keyframes  

  3. }, completion: nil)  

这个方法的几个参数与前几个使用过的动画方法参数一样。上面代码片段的意思是整个关键帧动画的持续时间为2秒、无延迟、无动画选项、执行完毕后无后续执行的代码。

注:该方法的动画选项不再是UIViewAnimationOptions,而是UIViewKeyframeAnimationOptions。具体的内容大家可以去查阅Apple的文档。

接下来我们要在animations闭包中添加关键帧了:

[cpp] view plaincopy

  1. UIView.animateKeyframesWithDuration(2, delay: 0, options: [], animations: {  

  2.     UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0.25, animations: {  

  3.         view.center.x += 200.0  

  4.     })  

  5. }, completion: nil)  

addKeyframeWithRelativeStartTime(_: relativeDuration: animations: )是UIView添加关键帧的方法,该方法有三个参数:

  • startTime:关键帧开始时间,该时间是相对整个关键帧动画持续时间的相对时间,一般值在0到1之间。如果为0,则表明这一关键帧从整个动画的第0秒开始执行,如果设为0.5,则表明从整个动画的中间开始执行。

  • relativeDuration:关键帧持续时间,该时间同样是相对整个关键帧动画持续时间的相对时间,一般值也在0到1之间。如果设为0.25,则表明这一关键帧的持续时间为整个动画持续时间的四分之一。

  • animations:设置视图动画属性的动画闭包。

我们解释一下上面这段代码。整个关键帧动画的持续时间为2秒,第一个关键帧从第0秒开始,运行0.5秒结束。下面我们完成其他三个关键帧:

[cpp] view plaincopy

  1. UIView.animateKeyframesWithDuration(2, delay: 0, options: [], animations: {  

  2.     UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0.25, animations: {  

  3.         view.center.x += 200.0  

  4.     })  

  5.     UIView.addKeyframeWithRelativeStartTime(0.25, relativeDuration: 0.25, animations: {  

  6.         view.center.y += 100.0  

  7.     })  

  8.     UIView.addKeyframeWithRelativeStartTime(0.5, relativeDuration: 0.25, animations: {  

  9.         view.center.x -= 200.0  

  10.     })  

  11.     UIView.addKeyframeWithRelativeStartTime(0.75, relativeDuration: 0.25, animations: {  

  12.         view.center.y -= 100.0  

  13.     })  

  14. }, completion: nil)  

第二个关键帧的开始时间为0.25,也就是从整个动画时间的第0.5时开始执行,同样持续0.5秒。后两个关键帧的参数就不难理解了。

现在整个代码看起来非常整洁,条理清晰,可读性非常好,而且可以有更精确的控制。即使再多几个关键帧也同样可以从容应对。

关键帧动画不仅仅用于同一个视图的分段动画,也可使使用于不同视图的组合动画,由于我们还没讲到图层动画,所以,开篇的示例动画中就使用了关键帧动画实现了多个视图的组合动画。

示例动画

在这个示例中虽然看起来是一个纸飞机视图的连续动画,但其实是由三个纸飞机视图组合而成的:

从图中可以看到其实是有三个纸飞机视图,只不过在界面加载之前2号和3号纸飞机视图的透明度都是为零。

整个动画是由这三个纸飞机视图通过关键帧动画组合而成:

图中标示出了三个飞机视图的运行轨迹、视图大小、视图透明度的状态,我们来看看代码如何实现:

[cpp] view plaincopy

  1. let zoomInScaleTransform = CGAffineTransformMakeScale(0.2, 0.2)  

  2. UIView.animateKeyframesWithDuration(3, delay: 0, options: [], animations: {  

  3.     UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0.2, animations: {  

  4.         self.customHeaderView.paperAirplane.center.x += self.view.frame.width  

  5.         self.customHeaderView.paperAirplane.center.y += -180  

  6.         self.customHeaderView.paperAirplane.transform = zoomInScaleTransform  

  7.     })  

  8.     UIView.addKeyframeWithRelativeStartTime(0.3, relativeDuration: 0.01, animations: {  

  9.         self.customHeaderView.paperAirplaneOpposite.alpha = 1  

  10.         self.customHeaderView.paperAirplaneOpposite.transform = zoomInScaleTransform  

  11.     })  

  12.     UIView.addKeyframeWithRelativeStartTime(0.3, relativeDuration: 0.5, animations: {  

  13.         self.customHeaderView.paperAirplaneOpposite.transform = CGAffineTransformIdentity  

  14.         self.customHeaderView.paperAirplaneOpposite.center.x -= self.view.frame.width  

  15.         self.customHeaderView.paperAirplaneOpposite.center.y += 90  

  16.     })  

  17.     UIView.addKeyframeWithRelativeStartTime(0.9, relativeDuration: 0.01, animations: {  

  18.         self.customHeaderView.paperAirplaneComeBack.alpha = 1  

  19.     })  

  20.     UIView.addKeyframeWithRelativeStartTime(0.9, relativeDuration: 0.2, animations: {  

  21.         self.customHeaderView.paperAirplaneComeBack.center.x += 33  

  22.     })  

  23. }, completion: { _ in  

  24.     self.restorePaperAirplaneStatus()  

  25. })  

大家看到这大家可能会有疑问了,三段动画怎么会有五个关键帧呢,我们来刨析一下:

  • 第一个关键帧:完成1号纸飞机视图运动到右上角并移出屏幕,视图逐渐变小的动画。该关键帧从整个动画的第0秒开始执行,持续时间为0.6秒。

  • 第二个关键帧:由于2号纸飞机视图的初始透明度为零,所以在第二个关键帧将透明度设为1,并且缩小视图。注意这两个动作需要在瞬间完成,所以relativeDuration设为0.01,一个极短的时间。开始时间为整个动画的第0.9秒开始,较第一个关键帧延迟0.3秒。

  • 第三个关键帧:与第二个关键帧同时开始执行,完成2号纸飞机视图从小变大、并且往左下角运动,一直移出屏幕。持续时间为1.5秒。

  • 第四个关键帧:与第二个关键帧作用相似,改变3号纸飞机视图的透明度,同样是在瞬间完成。

  • 第五个关键帧:与第四个关键帧同时执行, 完成向右移动的动画,持续0.6秒。

关键帧完成之后,在completion闭包中调用restorePaperAirplaneStatus()方法,恢复3个纸飞机视图的状态及位置,以便再次执行动画。

总结

大家在使用关键帧动画时,对于关键帧的开始时间和持续时间需要仔细设置,保证每个关键帧在合适的时间开始,执行恰当的持续时间。在必要时候也需要在关键帧里修改视图的一些状态,但要设置极短的持续时间,表示瞬间完成。

下一篇会向大家介绍在使用Auto Layout的情况下,如何通过约束实现动画,好了今天就先到这里吧。


声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
公众号网页更新缓存难题:如何避免版本更新后旧缓存影响用户体验?公众号网页更新缓存难题:如何避免版本更新后旧缓存影响用户体验?Mar 04, 2025 pm 12:32 PM

公众号网页更新缓存,这玩意儿,说简单也简单,说复杂也够你喝一壶的。你辛辛苦苦更新了公众号文章,结果用户打开还是老版本,这滋味,谁受得了?这篇文章,咱就来扒一扒这背后的弯弯绕绕,以及如何优雅地解决这个问题。读完之后,你就能轻松应对各种缓存难题,让你的用户始终体验到最新鲜的内容。先说点基础的。网页缓存,说白了就是浏览器或者服务器为了提高访问速度,把一些静态资源(比如图片、CSS、JS)或者页面内容存储起来。下次访问时,直接从缓存里取,不用再重新下载,速度自然快。但这玩意儿,也是个双刃剑。新版本上线,

如何高效地在网页中为PNG图片添加描边效果?如何高效地在网页中为PNG图片添加描边效果?Mar 04, 2025 pm 02:39 PM

本文展示了使用CSS为网页中添加有效的PNG边框。 它认为,与JavaScript或库相比,CSS提供了出色的性能,详细介绍了如何调整边界宽度,样式和颜色以获得微妙或突出的效果

如何使用HTML5表单验证属性来验证用户输入?如何使用HTML5表单验证属性来验证用户输入?Mar 17, 2025 pm 12:27 PM

本文讨论了使用HTML5表单验证属性,例如必需的,图案,最小,最大和长度限制,以直接在浏览器中验证用户输入。

< datalist>的目的是什么。 元素?< datalist>的目的是什么。 元素?Mar 21, 2025 pm 12:33 PM

本文讨论了html< datalist>元素,通过提供自动完整建议,改善用户体验并减少错误来增强表格。Character计数:159

HTML5中跨浏览器兼容性的最佳实践是什么?HTML5中跨浏览器兼容性的最佳实践是什么?Mar 17, 2025 pm 12:20 PM

文章讨论了确保HTML5跨浏览器兼容性的最佳实践,重点是特征检测,进行性增强和测试方法。

> gt;的目的是什么 元素?> gt;的目的是什么 元素?Mar 21, 2025 pm 12:34 PM

本文讨论了HTML< Progress>元素,其目的,样式和与< meter>元素。主要重点是使用< progress>为了完成任务和LT;仪表>对于stati

< meter>的目的是什么。 元素?< meter>的目的是什么。 元素?Mar 21, 2025 pm 12:35 PM

本文讨论了HTML< meter>元素,用于在一个范围内显示标量或分数值及其在Web开发中的常见应用。它区分了< meter>从< progress>和前

< iframe>的目的是什么。 标签?使用时的安全考虑是什么?< iframe>的目的是什么。 标签?使用时的安全考虑是什么?Mar 20, 2025 pm 06:05 PM

本文讨论了< iframe>将外部内容嵌入网页,其常见用途,安全风险以及诸如对象标签和API等替代方案的目的。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

仓库:如何复兴队友
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),