Core Animation编程 Part1/2

本文深入探讨了iOS中的动画机制,特别是UIKit和Core Animation两层动画系统的交互方式,详细介绍了UIView和CALayer之间的关系及其动画实现原理。

那啥,一忙起来就彻底忘记更新Blog了,目前移动产品开发也有了新的趋势,继续守在一个平台越来越难混了,HTML5在国内App开发中也逐步流行,因此未来移动开发工程师不仅仅要懂iOS/Android,多少还需要了解些H5,也就是Hybrid的开发模式,具体改日再叙。

今天继续扯iOS开发系列,聊聊iOS中牛逼闪闪的Core Animation,会有两个部分。先来了解下iOS中动画的层次:

最上层是UIKit,第二层是Core Anmation,然后iOS把这些动画效果用Open GL将在硬件上渲染出来。UIKit层中的动画API是作用于UIView,Core Animation层的动画API是作用于CALayer。我个人学习iOS的一个方法就是看类的头文件和相应的官方Reference文档。头文件可以很快查找出类的继承结构、属性和接口情况;Reference文档会详细介绍类的属性、方法以及需要了解的核心信息,没什么比这个文档说得更清楚了。

UIView Class Reference中讲到UIView主要负责三件事:

(1) 绘图和动画:利用UIKit、Core Graphics或者OpenGL ES绘制视图内容;有些UIView视图属性支持动画。

(2) 布局和子视图管理;一个视图可以关联零个或者多个子视图,如果有子视图,还可以定义子视的大小和位置;每个视图会定义它相对于父视图的尺寸变化(resizing)规则

(3) 事件处理:UIView继承自UIResponder,因此可以处理Touch事件和其他UIResponder中定义的事件;可以添加UIGestureRecognizer到UIView上,从而处理常见的几种手势操作。

UIView的渲染原理可以参考WWDC 2011的Session:Understanding UIKit Rendering以及objc.io的Getting Pixels onto the Screen,应该算是原理比较透彻了。

UIView中支持动画的属性有frame,bounds,center,alpha,backgroundColor,contentStretch(iOS 6之后不推荐使用,已经是Deprecated),transform。除了transform外,其他属性都很直白,这里transform是CGAffineTransform类型(CGAffineTransform Reference)。这里的transform是Affine Transform,即仿射变换,可以在二维中做各种视图变换。其本质就是个矩阵:

https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGAffineTransform/Art/equation01_2x.png

通过CGAffineTransform.h中的各种TransformMake接口就可以轻松实现二维视图的选择、放大、移动等操作。如果要了解如何使用这些仿射变换,可以参考文档《Quartz 2D Programming Guide》。Quartz 2D是iOS上的二维渲染引擎,提供了诸如透明Layer、Path绘图、离屏渲染、颜色管理、反锯齿渲染以及PDF相关的显示。基本上我们用的到这些接口的场景也就是:二维绘图、图形编辑功能、创建和显示位图,还有PDF相关的功能。细节这里就不表了,改日再叙。

UIView层的动画API相信大家都用过(非Block参数的UIView动画API实在太老旧,使用价值已经不大):

+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); // delay = 0.0, options = 0, completion = NULL

使用方法也很简单,就是在API的Block中改变需要实现动画的UIView属性值。iOS 7中又增加了针对Keyframe动画的API:

+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0); // start time and duration are values between 0.0 and 1.0 specifying time and duration relative to the overall time of the keyframe animation

Core Animation实际上就是作用在UIVIew属性layer上的动画,layer的类型是CALayer,定义在QuartzCore Framework中。从CALayer.h可以发现它和UIView实在太像了。它实现了NSCoding和CAMediaTiming协议,这个CAMediaTiming协议很有意思,稍后再说。QuartzCore Framework中除了CALayer以其各种子类外,比较重要的就是CAAction、CAAnimation、CAMediaTiming和CAMediaTimingFunction。

如何区分UIView和CALayer的关系?每个UIView都有layer属性,并且不会为空,实际是iOS系统为了图形渲染的优化,在Mac OS上NSView需要设置才会生成layer。layer不发生变化时其内容就是个CGImageRef。

CALayer有和UIView类似的属性frame、bounds、hidden、opaque,也有以下这些特别的属性:

  • position:
  • zPosition
  • anchorPoint
  • anchorPointZ
  • transform
  • cornerRadius
  • backgroundColor
  • borderColor
  • opacity
  • shadowRadius
  • shadowOffset
  • shadowColor
  • shadowPath
  • shouldRasterize
  • contents

说完CALayer,可以直接上Example,推荐Github的CA360,常见的Core Animation类型有涉及。

  • 基础动画类型(BasicAnimation):使用类CABasicAnimation,例子如下:
 CABasicAnimation *pulseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
  pulseAnimation.duration = .5;
  pulseAnimation.toValue = [NSNumber numberWithFloat:1.1];
  pulseAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
  pulseAnimation.autoreverses = YES;
  pulseAnimation.repeatCount = FLT_MAX;

CABasicAnimation集成至CAPropertyAnimation,表示基于属性变化的动画,其中和时间相关的属性都来自于CAMediaTiming Protocol,理解起来也很直观,

duration表示动画的持续时间,默认为0秒;

speed表示动画的速度,用于将父对象的时间对应当当前时间,默认为1,如果设置为2,就表示动画速度是父对象的2倍;

repeatCount表是动画重复的次数,默认为0;repeatDuration表示重复时候的持续时间,默认为0秒;autoreverses表示是否反向播放动画,默认为NO;

beginTime表示动画开始的时间,默认为0,它是相对于父对象的时间空间而言的,即如果一个Animation Group中的一个animation设置beginTime为2,则表示这个animation在animation开始的2秒后才会开始执行。如果要在不同Layer层级之间计算时间,需要用到CALayer的API:

- (CFTimeInterval)convertTime:(CFTimeInterval)t fromLayer:(CALayer *)l;
- (CFTimeInterval)convertTime:(CFTimeInterval)t toLayer:(CALayer *)l;

timeOffset表示动画对当前时间的偏移量,默认为0秒;举个例子加强理解,假设有个动画有五部分:1,2,3,4,5(分别占用一秒),如果这组动画的beginTime为1,则动画播放顺序为2,3,4,5,1;如果beginTime为2,则动画播放顺序为3,4,5,1,2;以此类推。如果需要从父对象的时间控件转换到当前对象的时间控件,使用如下公式:

t = (tp - begin) * speed + offset  

timeOffset的一个用途就是同过设置speed为0和offset为一个合适的值来暂停一个layer,可以见这个例子(获取到该layer上的当前时间,将speed降为0,同时将timeoffset置为当前时间,即可暂停动画到):

CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];  
layer.speed = 0.0;  
layer.timeOffset = pausedTime;  

fillMode表示表示动画的效果在有效期前后的赋值模式,有kCAFillModeForwards、kCAFillModeBackwards、kCAFillModeBoth、kCAFillModeRemoved几类,默认的为kCAFillModeRemoved。继续之前的假设动画有5个状态:1,2,3,4,5(分别占用一秒),如果动画的beginTime为1,同时duration为3,则实际的动画序列为2,3,4。这个动画添加到Animation Group中,Animation Group的duration为5,那么这个动画Group开始和结束的一秒内显示什么呢?如果fillMode是kCAFillModeForwards(动画属性向后拖后),则动画序列为2,3,4,5,5;如果fillMode是kCAFillModeBackwards(与kCAFillModeForwards相反),动画序列为1,2,3,4,4(最后一秒为4是由于动画不消除);如果fillMode是kCAFillModeBoth,则动画序列为1,2,3,4,5;默认的kCAFillModeRemoved则动画序列为空,2,3,4,空。解释应该比较清楚了吧。

回到最初的CABasicAnimation基础动画:

 CABasicAnimation *pulseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
  pulseAnimation.duration = .5;
  pulseAnimation.toValue = [NSNumber numberWithFloat:1.1];
  pulseAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
  pulseAnimation.autoreverses = YES;
  pulseAnimation.repeatCount = FLT_MAX;

第一句+ (instancetype)animationWithKeyPath:(NSString *)path; 表示需要修改的Layer属性,例如“position”,”tansform.scale”,可以对哪些属性进行修改,可以参考官方文档,后面几句设置的duration、autoreverses、repeatCount都已经解释过,toValue是设置动画属性的目标值,timingFunction是至动画的时间函数,就是个简单的贝塞尔曲线(Bezier Curve),如下图所示:

https://i-blog.csdnimg.cn/blog_migrate/ecd1115e45910ea8639256f105f9bbc3.png

分别代表kCAMediaTimingFunctionLinear, kCAMediaTimingFunctionEaseIn, 
kCAMediaTimingFunctionEaseOut, 
kCAMediaTimingFunctionEaseInEaseOut四类时间函数,简单点理解就是动画是匀速的(kCAMediaTimingFunctionLinear)还是先快后慢(kCAMediaTimingFunctionEaseOut),还是先慢后快(kCAMediaTimingFunctionEaseIn),还是慢快慢(kCAMediaTimingFunctionEaseInEaseOut)。kCAMediaTimingFunctionDefault对应的时间函数就是四个点决定的三次贝塞尔曲线:

http://ww2.sinaimg.cn/large/65cc0af7gw1dxm21gxjr0j.jpg

自定义时间函数当然也是可以的,参考How to create custom easing function with Core Animation

如果时间函数无法用简单的贝塞尔曲线表达,那么就得用到另一种动画了CAKeyframeAnimation关键帧动画,Part 2再继续聊。关于时间函数可以参考卢克的Blog 漫谈iOS Animation或者官方文档Animation Types and Timing Programming Guide

Example Source:CA360

CruiseYoung提供的带有详细书签的电子书籍目录 http://blog.youkuaiyun.com/fksec/article/details/7888251 该资料是《游戏编程精粹8》一书的随书光盘代码:共两部分,这是第1部分 游戏编程精粹8 基本信息 中文名: 游戏编程精粹8 原名: Game Programming Gems 8 作者: Adam Lake 图书分类: 软件 资源格式: PDF 版本: 插图版 出版社: Course Technology 书号: 1584507020 发行时间: 2010年03月01日 地区: 美国 语言: 英文 内容简介 本书为《Game Programming Gems》系列的第八卷。在这一版当中,我们将广泛地探讨重要的实时图形方面,如Larrabee, PlayStation 3, 以及DirectX 11计算着色器。此外在本书中,处在第一线的业内顶级开发商如:Blizzard,id, Bizarre Creations, Nexon,以及Intel's Advanced Visual Computing group,还分享了他们如何以最佳的方式利用图形硬件为游戏创建高品质视觉效果的真知灼见。 目录 Face -15 Contents -12 Preface -6 Contributors -1 Section 1 Graphics 1 Introduction 1 1.1 Fast Font Rendering with Instancing 3 1.2 Principles and Practice of Screen Space Ambient Occlusion 12 1.3 Multi-Resolution Deferred Shading 32 1.4 View Frustum Culling of Catmull-Clark Patches in DirectX 11 39 1.5 Ambient Occlusion Using DirectX Compute Shader 50 1.6 Eye-View Pixel Anti-Aliasing for Irregular Shadow Mapping 74 1.7 Overlapped Execution on Programmable Graphics Hardware 90 1.8 Techniques for Effective Vertex and Fragment Shading on the SPUs 101 Section 2 Physics and Animation 119 Introduction 119 2.1 A Versatile and Interactive Anatomical Human Face Model 121 2.2 Curved Paths for Seamless Character Animation 132 2.3 Non-Iterative, Closed-Form, Inverse Kinematic Chain Solver (NCF IK) 141 2.4 Particle Swarm Optimization for Game Programming 152 2.5 Improved Numerical Integration with Analytical Techniques 168 2.6 What a Drag: Modeling Realistic Three-Dimensional Air and Fluid Resistance 183 2.7 Application of Quasi-Fluid Dynamics for Arbitrary Closed Meshes 194 2.8 Approximate Convex Decomposition for Real-Time Collision Detection 202 Section 3 AI 211 Introduction 211 3.1 AI Level of Detail for Really Large Worlds 213 3.2 A Pattern-Based Approach to Modular AI for Games 232 3.3 Automated Navigation Mesh Generation Using Advanced Growth-Based Techniques 244 3.4 A Practical Spatial Architecture for Animal and Agent Navigation 256 3.5 Applying Control Theory to Game AI and Physics 264 3.6 Adaptive Tactic Selection in First-Person Shooter (FPS) Games 279 3.7 Embracing Chaos Theory: Generating Apparent Unpredictability through Deterministic Systems 288 3.8 Needs-Based AI 302 3.9 A Framework for Emotional Digital Actors 312 3.10 Scalable Dialog Authoring 323 3.11 Graph-Based Data Mining for Player Trace Analysis in MMORPGs 335 Section 4 General Programming 353 Introduction 353 4.1 Fast-IsA 355 4.2 Registered Variables 363 4.3 Efficient and Scalable Multi-Core Programming 373 4.4 Game Optimization through the Lens of Memory and Data Access 385 4.5 Stack Allocation 393 4.6 Design and Implementation of an In-Game Memory Profiler 402 4.7 A More Informative Error Log Generator 409 4.8 Code Coverage for QA 416 4.9 Domain-Specific Languages in Game Engines 428 4.10 A Flexible User Interface Layout System for Divergent Environments 442 4.11 Road Creation for Projectable Terrain Meshes 453 4.12 Developing for Digital Drawing Tablets 462 4.13 Creating a Multi-Threaded Actor-Based Architecture Using Intel® Threading Building Blocks 473 Section 5 Networking and Multiplayer 485 Introduction 485 5.1 Secure Channel Communication 487 5.2 Social Networks in Games: Playing with Your Facebook Friends 498 5.3 Asynchronous I/O for Scalable Game Servers 506 5.4 Introduction to 3D Streaming Technology in Massively Multiplayer Online Games 514 Section 6 Audio 539 Introduction 539 6.1 A Practical DSP Radio Effect 542 6.2 Empowering Your Audio Team with a Great Engine 553 6.3 Real-Time Sound Synthesis for Rigid Bodies 563 Section 7 General Purpose Computing on GPUs 573 Introduction 573 7.1 Using Heterogeneous Parallel Architectures with OpenCL 575 7.2 PhysX GPU Rigid Bodies in Batman: Arkham Asylum 590 7.3 Fast GPU Fluid Simulation in PhysX 602 Index 616 A 616 B 616 C 617 D 618 E 618 F 619 G 619 H 619 I 619 J 620 K 620 L 620 M 620 N 621 O 622 P 622 Q 623 R 623 S 623 T 624 U 625 V 625 W 625 X 625 Y 625 Z 625
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值