当前位置: 首页 > 科技观察

iOS开发基础知识:CoreAnimation(核心动画)

时间:2023-03-13 11:59:39 科技观察

CALayer与UIView的关系在iOS中,你能看到和触摸到的基本都是UIView,比如一个按钮,一个文本标签,一个文本输入框,图标等,这些都是UIView。其实UIView之所以能够显示在屏幕上,完全是因为它的内部层:在创建UIView对象时,会在UIView内部自动创建一个层(即CALayer对象),可以通过用户界面视图。@property(nonatomic,readonly,retain)CALayer*layer;当UIView需要显示在屏幕上时,会调用drawRect:方法进行绘制,会将所有内容绘制在自己的图层上。绘制完成后,系统会将图层复制到屏幕上,UIView的显示就完成了。也就是说,UIView本身没有显示功能,但是它的内层有显示功能。因此,通过调整CALayer对象,可以方便的调整UIView的一些外观属性。CALayer的基本属性宽高:@propertyCGRectbounds;position(默认指中点,具体由anchorPoint决定):@propertyCGPointposition;锚点(x,y范围为0-1),决定位置的意义:@propertyCGPointanchorPoint;背景颜色(CGColorRef类型):@propertyCGColorRefbackgroundColor;变形属性:@propertyCATransform3Dtransform;position和anchorPoint的作用@propertyCGPointposition;:用来设置CALayer在父层的位置,以父层的左上角为原点(0,0)@propertyCGPointanchorPoint;:叫做"anchorpoint"和"anchorpoint",它决定了CALayer上的哪个点将位于position属性指向的位置。以你的左上角为原点(0,0),它的x和y值范围是0到1,默认值为中心点(0.5,0.5)。anchorPoint和position的关系示例:如果锚点anchorPoint默认值为中点(0.5,0.5),图层的position设置为(0,0),也就是左上角的点父层,那么该层将只能看到父层的四分之一。AnchorPoint和位置隐式动画根层和非根层:每个UIView默认关联一个CALayer。我们可以称这个Layer为RootLayer(根层)。所有非根层都是手动创建的CALayer对象。有隐式动画。当修改一些不属于RootLayer的属性时,会默认自动生成一些动画效果,这些属性称为AnimatableProperties(动画属性)。几个常见的动画属性:bounds:用于设置CALayer的宽度和高度。修改此属性将生成缩放动画。backgroundColor:用于设置CALayer的背景色。修改该属性会产生背景色位置的渐变动画:用于设置CALayer的位置。修改此属性将生成平移动画。可以通过事务关闭隐式动画:[CATransactionbegin];//关闭隐式动画[CATransactionsetDisableActions:YES];self.myview.layer.position=CGPointMake(10,10);[CATransactioncommit];UIView和CALayer的选择可以通过CALayer做出和UIImageView一样的界面效果。既然CALayer和UIView都可以达到同样的显示效果,那么我们应该选择哪一个呢?事实上,UIView与CALayer相比,多了一种事件处理功能。也就是说,CALayer不能处理用户的触摸事件,但是UIView可以。因此,如果显示的东西需要和用户交互,就用UIView;如果您不需要与用户交互,请使用UIView或CALayer。当然,CALayer的性能会更高,因为它的事件处理函数更少,更轻量。为什么CALayer不能直接使用UIColor和UIImage呢?layer.backgroundColor=[UIColorredColor].CGColor;首先,在QuartzCore框架中定义了CALayer,在CoreGraphics框架中定义了CGImageRef和CGColorRef,在UIKit框架中定义了UIColor和UIImage。其次,QuartzCore框架和CoreGraphics框架可以跨平台使用,在iOS和MacOSX上都可以,但是UIKit只能在iOS上使用。因此,为了保证可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef。如果不是xcode5之后的版本,需要先添加QuartzCore.framework并导入对应的frameworkQuartzCore/QuartzCore.h才能使用。#p#CoreAnimation结构继承关系其中,灰色虚线表示继承关系,红色表示遵守约定。CoreAnimation中的所有类都符合CAMediaTiming协议。CAAnaimation是一个抽象类,没有动画效果,必须使用它的子类才能有动画效果。CAAnimationGroup和CATransition都有动画效果。CAAnimationGroup是一个可以同时缩放和旋转的动画组(同时多个动画)。CATransition是一种过渡动画,可用于界面之间的跳转(切换)。CAPropertyAnimation也是一个抽象类,没有动画效果,只有子类。CABasicAnimation和CAKeyframeAnimation:CABasicAnimation基础动画,做一些简单的效果。CAKeyframeAnimation帧动画,做一些连续流畅的动画。基本使用以基本动画为例:首先要有一个CALayer层。初始化一个CABasicAnimation对象,并为该对象设置相关属性。将基本动画对象添加到CALayer对象以启动动画。CALayer*layer=[CALayerlayer];...CABasicAnimation*animation=[CABasicAnimationanimation];anmation.keyPath=@"transform.scale";anmation.toValue=@0;[layeraddAnimation:animationforKey:nil];CAAnimation——介绍是所有动画对象的父类负责控制动画的持续时间和速度。它是一个抽象类,不能直接使用。您应该使用其特定的子类。基本属性说明:属性说明duration动画持续时间repeatCount重复次数,最大周期可设置为HUGE_VALF或MAXFLOATrepeatDuration重复时间removedOnCompletion默认为YES,表示动画执行完毕后从图层中移除,以及图形将返回到执行前的动画状态。如果想让layer一直显示动画执行后的状态,设置为NO,还要设置fillMode为kCAFillModeForwardsfillMode决定当前对象在非活动时间段内的行为。比如动画开始前或者动画结束前的beginTime,可以用来设置动画延迟执行的时间。如果要延迟2s,设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层当前时间。timingFunction调速函数控制动画运行RhythmdelegateAnimationagentfillMode属性设置:kCAFillModeRemoved这是默认值,也就是说在动画开始前和动画结束后,动画对图层没有影响。动画结束后,图层会回到之前的状态kCAFillModeForwards当动画结束时,图层会一直保持动画的状态***kCAFillModeBackwards动画开始前,只需要给一个图层添加动画,而层会立即进入动画的初始状态,等待动画开始。kCAFillModeBoth这个其实就是上面两个的综合。添加动画后开始前,图层处于动画初始状态。动画结束后,图层保持动画的状态。调速函数(CAMediaTimingFunction):kCAMediaTimingFunctionLinear(线性):匀速,给你一种相对静止的感觉然后减速到达目的地到达目的地。这是默认的动画行为。CAAnimation在类别@interfaceNSObject(CAAnimationDelegate)/*Calledwhentheanimationbeginsitsactiveduration.*///动画开始时调用-(void)animationDidStart:(CAAnimation*)anim;/*Calledwhentheanimationeithercompletesitsactivedurationor*isremovedfromtheobjectititisattachedto(i.e.thelayer).*istrueiftheanimationreachedtheendofitsactiveduration*withoutbeingremoved.*///动画结束后调用-(void)animationDidStop:(CAAnimation*)animfinished:(BOOL)flag;在@endCALayer上暂停和恢复动画#pragmamark暂停CALayer的动画-(void)pauseLayer:(CALayer*)layer{CFTimeIntervalpausedTime=[layerconvertTime:CACurrentMediaTime()fromLayer:nil];//让CALayer的时间停止移动layer.speed=0.0;//让CALayer的时间停留在pausedTime层的时刻。timeOffset=暂停时间;}#pragmamarkrestoreCALayer的动画-(void)resumeLayer:(CALayer*)layer{CFTimeIntervalpausedTime=layer.timeOffset;//1.让CALayer的时间继续走layer.speed=1.0;//2。取消最后记录的Staytimelayer.timeOffset=0.0;//3.取消上次设置的时间layer.beginTime=0.0;//4.计算暂停时间(这里也可以用CACurrentMediaTime()-pausedTime)CFTimeIntervaltimeSincePause=[layerconvertTime:CACurrentMediaTime()fromLayer:nil]-pausedTime;//5.设置相对于父坐标系的开始时间(向后timeSincePause)layer.beginTime=timeSincePause;}CAPropertyAnimation是CAAnimation的子类,也是一个抽象类。如果你想创建一个动画对象,你应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation。动画效果。例如指定@"position"为keyPath,修改CALayer的position属性的值,实现翻译的动画效果过程描述:随着动画的进行,keyPath对应属性的值逐渐从fromValue变为toValue,在持续时间的持续时间。keyPath内容是CALayer的动画属性。如果fillMode=kCAFillModeForwardsandremovedOnComletion=NO,那么动画执行完后,layer会一直显示动画执行完后的状态。但本质上,层的属性值仍然是动画执行前的初始值,并没有真正发生变化。CAKeyframeAnimation——关键帧动画关键帧动画也是CAPropertyAnimation的子类。与CABasicAnimation不同的是:CABasicAnimation只能从一个值(fromValue)变化到另一个值(toValue),而CAKeyframeAnimation会使用一个NSArray来保存这些值CABasicAnimation可以看作是一个只有2个关键帧的CAKeyframeAnimation属性描述:属性描述值NSArray对象。里面的元素被称为“关键帧”。动画对象会在指定的时间(duration)内依次显示values数组中的每个关键帧。path可以设置一个CGPathRef和CGMutablePathRef,让图层按照路径轨迹移动。path仅适用于anchorPoint和CALayer的位置。如果设置了路径,值将被忽略。keyTimes可以为对应的关键帧指定对应的时间点,取值范围为0~1.0。keyTimes中的每个时间值对应于values中的每个帧。如果不设置keyTimes,则每个关键帧的时间均分。#p#CAAnimationGroup——动画组动画组是CAAnimation的子类,可以保存一组动画对象。将CAAnimationGroup对象添加到图层后,该组中的所有动画对象都可以并发运行。默认情况下,一组动画对象同时运行,你也可以通过设置动画对象的beginTime属性来改变动画的开始时间。属性说明:属性说明animationsNSArrayCATransition用来保存一组动画对象——转场动画CATransition是CAAnimation的子类,用于转场动画,可以为图层移出屏幕和移入屏幕提供动画效果。iOS的过渡动画比MacOSX少了一点,UINavigationController通过CATransition实现了将controller的view推入屏幕的动画效果。属性说明:属性描述类型动画转场类型subtype动画转场方向startProgress动画起点(占整体动画的百分比)endProgress动画结束点(占整体动画的百分比)转场效果设置类型使用UIView动画函数实现转场动画-双视图+(void)transitionFromView:(UIView*)fromViewtoView:(UIView*)toViewduration:(NSTimeInterval)durationoptions:(UIViewAnimationOptions)optionscompletion:(void(^)(BOOLfinished))completion;参数说明持续时间动画持续时间选项动画类型动画将更改视图属性的代码放在此块中。动画完成后,将自动调用此块。CADisplayLinkCADisplayLink是一种由屏幕刷新率触发的时钟机制,每秒大约执行60次。CADisplayLink是一个计时器,它使绘图代码与视图的刷新频率保持同步,而NSTimer无法确保计时器实际触发的确切时间。使用方法:定义CADisplayLink并做一个触发调用方法将显示链接添加到主循环队列中//DefineCADisplayLink*link=[CADisplayLinkdisplayLinkWithTarget:selfselector:@selector(rotationChange)];//添加到主循环队列中[linkaddToRunLoop:[NSRunLoopmainRunLoop]forMode:NSDefaultRunLoopMode];开始和暂停