




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、用swift创建复杂的加载动画时至今日,iOS 应用商店已经拥有超过了140万 应用,让你自己的应用脱颖而出确实是个不小的挑战。不过,在你的应用掉入默默无闻的大黑洞之前,你拥有一个小小的机遇窗,它能帮你吸引用户的注意。想让你的用户喝彩尖叫,没有比应用加载界面更好的地方 ,在这个地方,你可以添加一个讨人喜欢的动画来作为你登陆或者认证流程的先导。在这个教程中,你将要学会如何利用先进的技术来创建一个流畅并且迷人的动画。开始吧!从这里下载启动项目,保存在一个合适的路径并用Xcode打开。打开 HolderView.swift 。 在这个UIView 的子类中,你可以添加些子层(在Layers的下级目录
2、中可以找到),使之像上面的动画一样生动OvalLayer.swift: 这是第一层,它从零尺寸扩展,然后会有一小段时间的摇摆TriangleLayer.swift: 接下来的这个层TriangleLayer会在OvalLayer 摇摆的时候出现,当此视图转动时,OvalLayer 会缩小到零尺寸,并在TriangleLayer 中消失。RectangleLayer.swift: 这个层是TriangleLayer 用于分类的可视化容器ArcLayer.swift: 这个层动画特效填充在RectangleLayer 中,这和杯子里填充了水(效果)非常相似打
3、开OvalLayer.swift, 启动项目已经包含了用于初始化这个层的代码和所有你会在动画里用到的Bezier path(对象)。你会看到expand(),wobble()和contract()方法都是空的。你可以通过参考这个指导书来填充这些方法。所有其他的 *Layer (以layer结尾)的文件都用了相似的方式构建。注意:如果你想要学习更多的Bezier paths,那就检出我们系列指导书 Modern Core Graphics with Swift最后,打开ViewController.swift 查看addHolderView()方法,这个方法添加了一个HolderVie
4、w 作为一个子视图,放到viewcontroller 视图的中间。这个视图将会放置所有的动画。viewcontroller仅仅需要把它放到屏幕上,这个视图将会照管好现行的动画代码。animateLabel() 是由类 HolderView 提供的代理回调函数,此类中你会用你完成的动画序列来填充。addButton()方法只是添加一个按钮到视图中,用于触摸和重启动画。编译并运行你的应用;你会看到一个空白屏幕。一个空白的画布-这就是用于开始创建你的新动画的完美的载体。在指导书的最后,你的应用会看起来是这样的:现在不需再费周折,我们开始吧添加一个椭圆这个动画从一个椭圆开始,椭圆是从屏幕中间扩展到视图
5、,然后在周围有点摇摆。打开 HolderView.swift ,在 HolderView 类的顶端附近声明如下的常量let ovalLayer = OvalLayer() 现在在此类的底部添加如下方法func addOval() layer.addSublayer(ovalLayer) ovalLayer.expand() 这段代码首先添加了你上面创建的 OverLayer 的实例作为一个子层到视图层,然后调用 expand() 方法,这是被切
6、掉的需要你来填充的函数之一来到 OvalLayer.swift 文件,添加如下代码到 expand() 中:func expand() var expandAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path") expandAnimation.fromValue = ovalPathSmall.CGPath ex
7、pandAnimation.toValue = ovalPathLarge.CGPath expandAnimation.duration = animationDuration expandAnimation.fillMode = kCAFillModeForwards expandAnimation.removedOnCompletion = false addAnimatio
8、n(expandAnimation, forKey: nil) 这个函数创建了一个 CABasicAnimation 的实例,这个实例用于改变椭圆从 ovalPathLarge.到 ovalPathSmall 的路径。启动项目为你提供了两者的Bezier paths。设置动画的 removedOnCompletion 的值为 false,fillMode 的值为 KCAFillModeForwards ,使得当动画结束的时候,椭圆保留它新的路径。最后,打开 ViewController.swift ,在 view.addSubview(holderVi
9、ew) 下的 addHolderView() 方法中添加如下的线条holderView.addOval() 将 holdview 添加到 ViewController 的视图中后,调用 addOval 方法来启动动画构建并运行你的应用,你的动画现在就会看起来像下面(图例)摇动椭圆使用视图中扩张的椭圆,下一步就是在椭圆的步调中设置一些反弹,使之摇摆起来打开 HolderView.swift,在此类的底部,添加下面的函数func wobbleOval() ovalLayer.wobble() 在 OvalLay
10、er 中调用被切掉的方法 wobble().现在打开 OverLayer.swift,在 wobble() 中添加如下代码func wobble() / 1 var wobbleAnimation1: CABasicAnimation = CABasicAnimation(keyPath: "path") wobbleAnimation1.fromValue = ovalP
11、athLarge.CGPath wobbleAnimation1.toValue = ovalPathSquishVertical.CGPath wobbleAnimation1.beginTime = 0.0 wobbleAnimation1.duration = animationDuration / 2 var wob
12、bleAnimation2: CABasicAnimation = CABasicAnimation(keyPath: "path") wobbleAnimation2.fromValue = ovalPathSquishVertical.CGPath wobbleAnimation2.toValue = ovalPathSquishHorizontal.CGPath wobbleAnimati
13、on2.beginTime = wobbleAnimation1.beginTime + wobbleAnimation1.duration wobbleAnimation2.duration = animationDuration / 3 var wobbleAnimation3: CABasicAnimation = CABasicAnimation(key
14、Path: "path") wobbleAnimation3.fromValue = ovalPathSquishHorizontal.CGPath wobbleAnimation3.toValue = ovalPathSquishVertical.CGPath wobbleAnimation3.beginTime = wobbleAnimation2.beginTime + wobb
15、leAnimation2.duration wobbleAnimation3.duration = animationDuration / 4 var wobbleAnimation4: CABasicAnimation = CABasicAnimation(keyPath: "path") wobbleAnimation4.fromVa
16、lue = ovalPathSquishVertical.CGPath wobbleAnimation4.toValue = ovalPathLarge.CGPath wobbleAnimation4.beginTime = wobbleAnimation3.beginTime + wobbleAnimation3.duration wobbleAnimation4.duration = ani
17、mationDuration / 5 var wobbleAnimationGroup: CAAnimationGroup = CAAnimationGroup() wobbleAnimationGroup.animations = wobbleAnimation1, wobbleAnimation2, wobbleAnimation3,
18、0; wobbleAnimation4 wobbleAnimationGroup.duration = wobbleAnimation4.beginTime + wobbleAnimation4.duration wobbleAnimationGroup.repeatCount = 2 addAnimation(wobbleAnimationGroup, forKey: nil)&
19、#160; 代码真够多的。但断句还是很讲究的。 接下来要做的是:从大路径下降到被垂直压扁的动画从垂直压扁变成水平和垂直都压扁和垂直挤压(动画)切换回到大路径结束动画把你所有的动画合并到CAAnimationGroup组,并把这个动画组添加到你的 OvalLayout 中。每一个随后的动画的 beginTime 都是其前一个动画和动画持续时间的 beginTime 总和。你重复动画组两次就会给你一种摆动出稍微拉长的感觉尽管你现在拥有产生摇摆动画的所有代码,你还是不能调用你的新动画我们回到 HolderView.swift,在 addOval() 结尾处添加如下代码NSTimer.sch
20、eduledTimerWithTimeInterval(0.3, target: self, selector: "wobbleOval", userInfo: nil, repeats:
21、;false) 在这里,你创建了一个timer定时器,它会在OvalLayer已经结束扩张后调用 wobbleOval()编译并运行你的应用,检查下你的新动画。这有点微妙,但那对一个真正的明快的动画是一个重要的因素。你不再需要那些满屏幕都是乱飞的东西了。开始变身是时候来电有趣的东西了。你将要把一个椭圆变身成为一个三角形。在用户眼里,这个转变应该看上去无缝连接的。要做到这些,你会用到两个相同颜色的分离的形状。打开HolderView.swift,在HolderView类的顶端稍微靠近你早些时候添加的 OvalLayer 属性的下面添加如下代码let triangleLayer
22、 = TriangleLayer() 这里声明了一个 TriangleLayer 类的常量,正如你在 OvalLayer 中做的一样现在,让wobbleOval()方法看上去像这样:func wobbleOval() / 1 layer.addSublayer(triangleLayer) / Add this line ovalLayer.wobble()
23、 / 2 / Add the code below NSTimer.scheduledTimerWithTimeInterval(0.9, target: self,
24、; selector: "drawAnimatedTriangle", userInfo: nil,
25、0; repeats: false) 上面的代码做了如下这些事情:这行(代码)添加了一个 TiangleLayer 实例,这个实例在稍早的时候作为HolderView层的子层已经被初始化过了。正如你所知道的,因为这个摇摆动画在1.8s
26、的总间隔时间内运行两次,所以在中间点启动变形过程会是一个非常好的地方。因此,你要添加一个定时器timer,它在延迟0.9s之后执行drawAnimatedTriangle()注意:找到动画的正确的间隔或延迟需要反复实验,这也是一个好的动画和一个极好的动画区别。我鼓励你去修补你的动画,让它们看上去完美。这可能要花点时间,但确是值得的。接下来,在此类的底部添加如下的函数。func drawAnimatedTriangle() triangleLayer.animate() 这个方法会被你刚刚加入到 wobbleOval(
27、) 中的timer定时器调用。现在打开 TriangleLayer.swift,添加如下代码到 animate()func animate() var triangleAnimationLeft: CABasicAnimation = CABasicAnimation(keyPath: "path") triangleAnimationLeft.fromValue = trianglePathSmall.CGPath
28、 triangleAnimationLeft.toValue = trianglePathLeftExtension.CGPath triangleAnimationLeft.beginTime = 0.0 triangleAnimationLeft.duration = 0.3 var triangleAnimationRight: CABasicAnim
29、ation = CABasicAnimation(keyPath: "path") triangleAnimationRight.fromValue = trianglePathLeftExtension.CGPath triangleAnimationRight.toValue = trianglePathRightExtension.CGPath triangleAnimationRight.begi
30、nTime = triangleAnimationLeft.beginTime + triangleAnimationLeft.duration triangleAnimationRight.duration = 0.25 var triangleAnimationTop: CABasicAnimation = CABasicAnimation(keyPath: "path"
31、) triangleAnimationTop.fromValue = trianglePathRightExtension.CGPath triangleAnimationTop.toValue = trianglePathTopExtension.CGPath triangleAnimationTop.beginTime = triangleAnimationRight.beginTime + triangleA
32、nimationRight.duration triangleAnimationTop.duration = 0.20 var triangleAnimationGroup: CAAnimationGroup = CAAnimationGroup() triangleAnimationGroup.animations = triangleAnimationLeft, triangl
33、eAnimationRight, triangleAnimationTop triang
34、leAnimationGroup.duration = triangleAnimationTop.beginTime + triangleAnimationTop.duration triangleAnimationGroup.fillMode = kCAFillModeForwards triangleAnimationGroup.removedOnCompletion = false addAnimation(
35、triangleAnimationGroup, forKey: nil) 这段代码使三角层TriangleLayer的角一个挨一个的被弹拉成为椭圆 OvalLayer 层的摆动。Bezier path已经作为启动工程的一部分被定义好。左边的角首先执行,接下来是右边的角,最后是上面的。你完成这个(动画)需要借助创建三个基于路径的CABasicAnimation类的实例, CABasicAnimation 类已经被你添加到 CAAnimationGroup 组中,而组则被放到了 TriangleLayer 中。构建并运行你的应用,看看当前动画的状态.完成变
36、形为了完成变形过程,你需要在缩小OvalLayer椭圆层的同时,对 HolderView 旋转360度,让 TriangleLayer 三角层单独隔离出来。打开 HolderView.swift,在 drawAnimatedTriangle(): 尾部添加如下代码NSTimer.scheduledTimerWithTimeInterval(0.9, target: self, selector: "spinAndTransform",
37、60; userInfo: nil, repeats: false) 这里设置了一个定时器timer,用于在三角形动画结束后触发。0.9s的时间还次用反复实验来确定现在在这个类的底部添加如下的函数。func spinAndTransform() / 1
38、160;layer.anchorPoint = CGPointMake(0.5, 0.6) / 2 var rotationAnimation: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z") rotationAnimation.toValue = CG
39、Float(M_PI * 2.0) rotationAnimation.duration = 0.45 rotationAnimation.removedOnCompletion = true layer.addAnimation(rotationAnimation, forKey: nil) / 3 ovalLa
40、yer.contract() 你之前创建的定时器添加了这段代码,定时器会在椭圆停止摆动并且三角行的角出现的时候调用这个函数。在这里我们看下这个函数更详细的(介绍)更新层的锚点到略微靠近视图中间的下方。这提供了一个看上去更加自然的旋转。这是由于椭圆和三角形事实上比视图中心在垂直方向上略微偏移。因此,如果视图围绕中心旋转,椭圆和三角形可能会垂直方向移动应用一个CABasicAnimation类来对层做360度旋转,或者2*pi的弧度。旋转是围绕着Z轴,Z轴就是穿过屏幕,垂直于屏幕平面的轴在OvalLayer中调用contract()来展示动画,这个动画会削减椭圆的尺寸直到消失
41、现在打开 OvalLayer.swift,添加如下代码到 contract() 方法func contract() var contractAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path") contractAnimation.fromValue = ovalPathLarge.CGPath contract
42、Animation.toValue = ovalPathSmall.CGPath contractAnimation.duration = animationDuration contractAnimation.fillMode = kCAFillModeForwards contractAnimation.removedOnCompletion = false addAnimat
43、ion(contractAnimation, forKey: nil) 这段代码应用 CABasicAnimation 类,将 OvalLayer 设置它的初始路径 ovalPathSmall。构建并运行你的应用程序,当动画完成的时候,只有三角形应该被留在屏幕上。绘制容器在下面这部分,你将要绘画一个矩形容器,用于创建一个闭合圈。你将会用到 RectangleLayer 的描边属性。你需要这样做两次,将红色和蓝色都作为描边色。打开 HolderView.swift, 像下面这样声明两个 RectangularLayer 常量,(位置)就在你稍早时候 tr
44、iangleLayer 属性的下面let redRectangleLayer = RectangleLayer()let blueRectangleLayer = RectangleLayer() 接下来添加如下代码到 spinAndTransform(): 的尾部。NSTimer.scheduledTimerWithTimeInterval(0.45, target: self,
45、60; selector: "drawRedAnimatedRectangle",
46、; userInfo: nil, repeats: false) NSTimer.scheduledTimerWithTimeInterval(0.65, target: self,
47、 selector: "drawBlueAnimatedRectangle",&
48、#160; userInfo: nil, repeats: false) 这里创建
49、两个定时器timer分别调用 drawRedAnimatedRectangle() 和 drawBlueAnimatedRectangle() 。旋转动画结束后,首先需要画出矩形,当红色矩形描边绘画接近完成的时候,蓝色矩形描边开始。添加下面两个方法头此类的底部func drawRedAnimatedRectangle() layer.addSublayer(redRectangleLayer) redRectangleLayer.animateStrokeWithColor(Colors.red)
50、0; func drawBlueAnimatedRectangle() layer.addSublayer(blueRectangleLayer) blueRectangleLayer.animateStrokeWithColor(Colors.blue) 一旦你添加矩形层 RectangleLayer 作为 HolderView 的子层,你就要调用 animateStrokeWithColor(color:) 并通过适当的颜色来绘画出边线。现在打开
51、 RectangleLayer.swift, 像下面这样填充 animateStrokeWithColor(color:)func animateStrokeWithColor(color: UIColor) strokeColor = color.CGColor var strokeAnimation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd&
52、quot;) strokeAnimation.fromValue = 0.0 strokeAnimation.toValue = 1.0 strokeAnimation.duration = 0.4 addAnimation(strokeAnimation, forKey: nil) 这段代码通过添加一个 CABasicAnimation对象,在 Rectan
53、gleLayer 矩形层周围绘画了一个描边。CAShapeLayer 的 strokeEnd 的 key(也就是keyPath)指示了在路径周围多远的距离停止描边。通过将这个属性值从0调到1,你会产生一种路径被从开始到结束都被绘画的错觉。 而从1到0,将会产生整个路径被抹去的错觉。编译并运行你的应用,查看两个描边是如何看起来像他们构建的容器的。填充容器动画的下一步就是填充容器。你要寻找到的效果就像是水填充到玻璃杯中。这是个非常棒的视觉特效,使之为一个大的飞溅特效打开 HolderView.swift,在 RectangleLayer 属性稍靠下添加如下的常量let arcLayer&
54、#160;= ArcLayer() 现在在drawBlueAnimatedRectangle():尾部添加如下的代码NSTimer.scheduledTimerWithTimeInterval(0.40, target: self, selector: "drawArc",
55、60; userInfo: nil, repeats: false) 这(段代码)创建了一个定时器,用于当蓝色 RectangleLayer 完成绘画后调用 drawArc()在类的结尾添加如下的函数func drawArc() layer.addSublayer(
56、arcLayer) arcLayer.animate() 这段代码是在你动画填充之前,添加了上面已经创建ArcLayer 的实例对象到HolderView 层。打开ArcLayer.swift 然后添加如下代码到animate():func animate() var arcAnimationPre: CABasicAnimation = CABasicAnimation(keyPath: "path")
57、; arcAnimationPre.fromValue = arcPathPre.CGPath arcAnimationPre.toValue = arcPathStarting.CGPath arcAnimationPre.beginTime = 0.0 arcAnimationPre.duration = animationDuration &
58、#160;var arcAnimationLow: CABasicAnimation = CABasicAnimation(keyPath: "path") arcAnimationLow.fromValue = arcPathStarting.CGPath arcAnimationLow.toValue = arcPathLow.CGPath arcAnimationLow.begi
59、nTime = arcAnimationPre.beginTime + arcAnimationPre.duration arcAnimationLow.duration = animationDuration var arcAnimationMid: CABasicAnimation = CABasicAnimation(keyPath: "path")
60、0; arcAnimationMid.fromValue = arcPathLow.CGPath arcAnimationMid.toValue = arcPathMid.CGPath arcAnimationMid.beginTime = arcAnimationLow.beginTime + arcAnimationLow.duration arcAnimationMid.duration
61、= animationDuration var arcAnimationHigh: CABasicAnimation = CABasicAnimation(keyPath: "path") arcAnimationHigh.fromValue = arcPathMid.CGPath arcAnimationHigh.toValue = arcPathH
62、igh.CGPath arcAnimationHigh.beginTime = arcAnimationMid.beginTime + arcAnimationMid.duration arcAnimationHigh.duration = animationDuration var arcAnimationComplete: CABasicAnimation = CAB
63、asicAnimation(keyPath: "path") arcAnimationComplete.fromValue = arcPathHigh.CGPath arcAnimationComplete.toValue = arcPathComplete.CGPath arcAnimationComplete.beginTime = arcAnimationHigh.beginTime +&
64、#160;arcAnimationHigh.duration arcAnimationComplete.duration = animationDuration var arcAnimationGroup: CAAnimationGroup = CAAnimationGroup() arcAnimationGroup.animations = arcAnimationPre, ar
65、cAnimationLow, arcAnimationMid, arcAnimationHigh, arcAnimationComplete
66、; arcAnimationGroup.duration = arcAnimationComplete.beginTime + arcAnimationComplete.duration arcAnimationGroup.fillMode = kCAFillModeForwards arcAnimationGroup.removedOnCompletion = false addAnimat
67、ion(arcAnimationGroup, forKey: nil) 这个动画和之前的摇摆动画很相似。你创建了一个 CAAnimationGroup 动画组,动画组中包含五个基于路径的 CABasicAnimation 实例对象。每个路径因高度递增而有了稍微不同的弧,这些路径也是启动项目的一部分。最后,将 CAAnimationGroup 动画组应用到层中,并使得动画组在完成的时候不会被移除,因而当动画完成的时候,它依然保留了自己的状态。构建并运行你的应用,看看这个神奇的展开吧。完成动画剩下要做的就是扩展蓝色的HolderView视图来填充整个屏幕,
68、并且添加一个UILabel作为一个logo添加到视图中打开 HolderView.swift,在drawArc() 的结尾添加如下代码NSTimer.scheduledTimerWithTimeInterval(0.90, target: self, selector: "expandView", &
69、#160; userInfo: nil, repeats: false) 这(段代码)创建了一个定时器,用于在 ArcLayer 填充到容器后调用 expandView()现在,添加下面的函数到同一个类的底部:func expandView() / 1
70、160; backgroundColor = Colors.blue / 2 frame = CGRectMake(frame.origin.x - blueRectangleLayer.lineWidth,
71、160; frame.origin.y - blueRectangleLayer.lineWidth, frame.size.width + blueRectangleLayer.lineWidth * 2,
72、 frame.size.height + blueRectangleLayer.lineWidth * 2) / 3 layer.sublayers = nil / 4 UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: self.frame = self.parent
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 美术作品鉴赏与艺术史教育计划
- 学生社团活动的组织方案计划
- 深入分析仓库物流成本的控制计划
- 2025光伏低压并网开关
- 班级学习环境的优化计划
- 渠道管理提升方案计划
- 保安工作总结计划电力行业保安工作的设备检修
- 高效的英语学习方法与实践探索
- 湖南2025年01月湖南省保靖县事业单位2025年公开引进16名急需紧缺人才笔试历年典型考题(历年真题考点)解题思路附带答案详解
- 浙江2025年02月舟山市水利局招考1名劳务派遣人员笔试历年典型考题(历年真题考点)解题思路附带答案详解
- 伤口的延续性护理
- 药品批发公司培训课件模板
- 《教科版一国两制》课件
- 急性肾挫裂伤护理查房课件
- 脑出血个案护理计划
- 小学生电力科普小讲座(课件)-小学常识科普主题班会
- 第八次课-冶金考古
- 临床医生如何进行临床科研-2
- 硝酸镁法制取浓硝酸
- PFMEA-失效模式分析案例
- 国家药监局医疗器械技术审评检查大湾区分中心第二批员额制人员公开招聘(2023年)模拟预测(共1000题)笔试备考题库及答案解析
评论
0/150
提交评论