iOS QuartzCore框架(Core Animation)、Quartz2D、UIBezierPath、CALayer

2,320 阅读18分钟

QuartzCore框架: Core Animation动画相关
一些其他动画
Core Graphics: Quartz2D
demo-知识点-自定义视图

动画相关

核心动画(Core Animation)

开发步骤

  1. 使用它需要先添加QuartzCore.framework框架和引入主头文件<QuartzCore/QuartzCore.h>
  2. 初始化一个CAAnimation对象,并设置一些动画相关属性
  3. 通过调用CALayer的addAnimation:forKey:方法增加CAAnimation对象到CALayer中,这样就能开始执行动画了
  4. 通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画

注意

  1. Core Animation是直接作用在CALayer上的,并非UIView。CALayer中很多属性都可以通过CAAnimation实现动画效果,包括:opacity、position、transform、bounds、contents等(可以在API文档中搜索:CALayer Animatable Properties)
  2. Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程

CAAnimation继承结构

!

CAAnimation 所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类 属性解析:(红色代表来自CAMediaTiming协议的属性)

  • duration:动画的持续时间
  • repeatCount:动画的重复次数
  • repeatDuration:动画的重复时间
  • removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
  • fillMode:决定当前对象在非active时间段的行为。比如动画开始之前,动画结束之后。
    fillMode属性值(要想fillMode有效,最好设置removedOnCompletion = NO)
    • kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
    • kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
    • kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。
    • kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态
  • beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2 CACurrentMediaTime()为图层的当前时间
  • timingFunction:速度控制函数,控制动画运行的节奏(CAMediaTimingFunction)
    • kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感
    • kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
    • kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
    • kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。
  • delegate:动画代理
    - (void)animationDidStart:(CAAnimation *)anim;
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

CAPropertyAnimation

CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:CABasicAnimationCAKeyframeAnimation 属性解析:

  • keyPath:通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@”position”为keyPath,就修改CALayer的position属性的值,以达到平移的动画效果
CABasicAnimation 基本动画

CAPropertyAnimation的子类 属性解析:

  • fromValue:keyPath相应属性的初始值
  • toValue:keyPath相应属性的结束值
  • 随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue
  • 如果fillMode=kCAFillModeForwardsremovedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。比如,CALayer的position初始值为(0,0),CABasicAnimation的fromValue为(10,10),toValue为(100,100),虽然动画执行完毕后图层保持在(100,100)这个位置,实质上图层的position还是为(0,0)。
CAKeyframeAnimation 关键帧动画

CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值。 属性解析:

  • values:就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
  • path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略
  • keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧。当keyTimes没有设置的时候,各个关键帧的时间是平分的

CABasicAnimation可看做是最多只有2个关键帧的CAKeyframeAnimation

CAAnimationGroup

CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行。
属性解析:

  • animations:用来保存一组动画对象的NSArray
  • 默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间

CATransition

CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点。UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果 属性解析:

  • type:动画过渡类型
  • subtype:动画过渡方向
  • startProgress:动画起点(在整体动画的百分比)
  • endProgress:动画终点(在整体动画的百分比)

转场动画过渡效果

UIView动画

UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持。执行动画所需要的工作由UIView类自动完成,但仍要在希望执行动画时通知视图,为此需要将改变属性的代码放在[UIView beginAnimations:nil context:nil][UIView commitAnimations]之间。

常见方法解析:

+ (void)setAnimationDelegate:(id)delegate: 设置动画代理对象,当动画开始或者结束时会发消息给代理对象 + (void)setAnimationWillStartSelector:(SEL)selector: 当动画即将开始时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector + (void)setAnimationDidStopSelector:(SEL)selector: 当动画结束时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector + (void)setAnimationDuration:(NSTimeInterval)duration: 动画的持续时间,秒为单位 + (void)setAnimationDelay:(NSTimeInterval)delay: 动画延迟delay秒后再开始 + (void)setAnimationStartDate:(NSDate *)startDate: 动画的开始时间,默认为now + (void)setAnimationCurve:(UIViewAnimationCurve)curve: 动画的节奏控制 + (void)setAnimationRepeatCount:(float)repeatCount: 动画的重复次数 + (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses: 如果设置为YES,代表动画每次重复执行的效果会跟上一次相反 + (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache: 设置视图view的过渡效果,transition指定过渡类型,cache设置YES代表使用视图缓存,性能较好

Block动画

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

属性解析: duration:动画的持续时间 delay:动画延迟delay秒后开始 options:动画的节奏控制 animations:将改变视图属性的代码放在这个block中 completion:动画结束后,会自动调用这个block

+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;

+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion;

方法调用完毕后,相当于执行了下面两句代码: // 添加toView到父视图[fromView.superview addSubview:toView]; // 把fromView从父视图中移除[fromView.superview removeFromSuperview];

例如一个视图淡出屏幕,另外一个视图出现的代码:
[UIView animateWithDuration:1.0 animations:^{
    firstView.alpha = 0.0;
    secondView.alpha = 1.0;
}];
如何实现连续的动画?可以在completion代码块中添加动画。下面是实例代码:
[UIView animateWithDuration:2.0 animations:^{
    oldImageView.alpha =0.0;
    newImageView.alpha = 1.0;
    //imageView.center = CGPointMake(500.0, 512.0);
} completion:^(BOOL finished) { 
    [UIView animateWithDuration:4.0 animations:^{ 
        newImageView.center = CGPointMake(500.0, 512.0);
    }];
}];

CALayer 动画

#pragma mark 暂停CALayer的动画
-(void)pauseLayer:(CALayer*)layer {
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    // 让CALayer的时间停止走动
    layer.speed = 0.0;
    // 让CALayer的时间停留在pausedTime这个时刻
    layer.timeOffset = pausedTime;
}
#pragma mark 恢复CALayer的动画
-(void)resumeLayer:(CALayer*)layer {
    CFTimeInterval pausedTime = layer.timeOffset;
    // 1. 让CALayer的时间继续行走
    layer.speed = 1.0;
    // 2. 取消上次记录的停留时刻
    layer.timeOffset = 0.0;
    // 3. 取消上次设置的时间
    layer.beginTime = 0.0;
    // 4. 计算暂停的时间(这里也可以用CACurrentMediaTime()-pausedTime)
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    // 5. 设置相对于父坐标系的开始时间(往后退timeSincePause)
    layer.beginTime = timeSincePause;
}
CADisplayLink

CADisplayLink是一种以屏幕刷新频率触发的时钟机制,每秒钟执行大约60次左右。 CADisplayLink是一个计时器,可以使绘图代码与视图的刷新频率保持同步,而NSTimer无法确保计时器实际被触发的准确时间。 使用方法:

  1. 定义CADisplayLink并制定触发调用方法
  2. 将显示链接添加到主运行循环队列

UIImageView的帧动画

UIImageView可以让一系列的图片在特定的时间内按顺序显示 相关属性解析: animationImages:要显示的图片(一个装着UIImage的NSArray) animationDuration:完整地显示一次animationImages中的所有图片所需的时间 animationRepeatCount:动画的执行次数(默认为0,代表无限循环) 相关方法解析: - (void)startAnimating;: 开始动画 - (void)stopAnimating;: 停止动画 - (BOOL)isAnimating;: 是否正在运行动画

UIActivityIndicatorView

是一个旋转进度轮,可以用来告知用户有一个操作正在进行中,一般用initWithActivityIndicatorStyle初始化 方法解析: - (void)startAnimating; 开始动画 - (void)stopAnimating; 停止动画 - (BOOL)isAnimating;; 是否正在运行动画 UIActivityIndicatorViewStyle有3个值可供选择: UIActivityIndicatorViewStyleWhiteLarge //大型白色指示器 UIActivityIndicatorViewStyleWhite&nbsp //标准尺寸白色指示器 UIActivityIndicatorViewStyleGray //灰色指示器,用于白色背景

Quartz2D

Quartz2D的API是纯C语言的。来自于Core Graphics。是一个二维绘图引擎,同时支持iOS和Mac系统。 数据类型和函数基本都以CG作为前缀,CGContextRef、CGPathRef、CGContextStrokePath(ctx)。 Quartz2D在iOS开发中很重要的一个价值是:自定义view(自定义UI控件)。

Quartz 2D能完成的工作

  • 绘制图形 : 线条\三角形\矩形\圆\弧等
  • 绘制文字
  • 绘制\生成图片(图像)
  • 读取\生成PDF
  • 截图\裁剪图片
  • 自定义UI控件
  • 涂鸦\画板
  • 手势解锁
Quartz2D提供了以下几种类型的Graphics Context:
  • Bitmap Graphics Context
  • PDF Graphics Context
  • Window Graphics Context
  • Layer Graphics Context
  • Printer Graphics Context

    相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上:

图形上下文(Graphics Context)

是一个CGContextRef类型的数据。

图形上下文的作用
  1. 保存绘图信息、绘图状态
  2. 决定绘制的输出目标(绘制到什么地方去?) 输出目标可以是PDF文件、Bitmap或者显示器的窗口上)

如何利用Quartz2D自定义view?(自定义UI控件)

首先,得有图形上下文,因为它能保存绘图信息,并且决定着绘制到什么地方去。 其次,那个图形上下文必须跟view相关联,才能将内容绘制到view上面。

自定义view的步骤
  1. 新建一个类,继承自UIView
  2. 实现 - (void)drawRect:(CGRect)rect方法,然后在这个方法中取得跟当前view相关联的图形上下文
  3. 绘制相应的图形内容
  4. 利用图形上下文将绘制的所有内容渲染显示到view上面
为什么要实现drawRect:方法才能绘图到view上?

因为在drawRect:方法中才能取得跟view相关联的图形上下文; View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,因此,绘制的东西其实是绘制到view的layer上去了; View之所以能显示东西,完全是因为它内部的layer;

drawRect:方法在什么时候被调用?

当view第一次显示到屏幕上时(被加到UIWindow上显示出来) 调用view的setNeedsDisplay或者setNeedsDisplayInRect:

Quartz2D代码

Quartz2D绘图的代码步骤
  1. 获得图形上下文 CGContextRef ctx = UIGraphicsGetCurrentContext();

  2. 拼接路径(下面代码是搞一条线段) CGContextMoveToPoint(ctx, 10, 10); CGContextAddLineToPoint(ctx, 100, 100);

  3. 绘制路径 CGContextStrokePath(ctx); // CGContextFillPath(ctx);

常用拼接路径函数
  • 新建一个起点
    void CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)
  • 添加新的线段到某个点
    void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)
  • 添加一个矩形
    void CGContextAddRect(CGContextRef c, CGRect rect)
  • 添加一个椭圆
    void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)
  • 添加一个圆弧
    void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
常用绘制路径函数
  • Mode参数决定绘制的模式
    void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)
  • 绘制空心路径
    void CGContextStrokePath(CGContextRef c)
  • 绘制实心路径
    void CGContextFillPath(CGContextRef c)

提示:一般以CGContextDraw、CGContextStroke、CGContextFill开头的函数,都是用来绘制路径的

图形上下文栈的操作
  • 将当前的上下文copy一份,保存到栈顶(那个栈叫做”图形上下文栈”)
    void CGContextSaveGState(CGContextRef c)
  • 将栈顶的上下文出栈,替换掉当前的上下文
    void CGContextRestoreGState(CGContextRef c)
画线drawLine
  1. 获取上下文件UIGraphicsGetCurrentContext();
  2. 设置起点CGContextMoveToPoint(ctx, 10, 10);
  3. 添加连接点AddLineToPoint(ctx, 110, 10);
  4. 渲染CGContextStrokePath(ctx);
  5. 设置线宽CGContextSetLineWidth(ctx, 3);
  6. 设置线的颜色CGContextSetRGBStrokeColor(ctx, 1, 0, 0, 1);
  7. 再添加1个连接点完成矩形绘制
  8. 设置线的首尾样式CGContextSetLineCap(ctx, kCGLineCapButt);
  9. 设置线的连接样式CGContextSetLineJoin(ctx, kCGLineJoinRound);
画矩形drawRectangle
  1. 获取上下文件UIGraphicsGetCurrentContext();
  2. 设置起点,并连接四个点成为矩形 CGContextMoveToPoint(ctx, 10, 10) AddLineToPoint(ctx, 110, 10); AddLineToPoint(ctx, 110, 110); AddLineToPoint(ctx, 110, 10); AddLineToPoint(ctx, 10, 10);
  3. 画空心CGContextStrokePath(ctx)
  4. 画实心CGContextFillPath(ctx);
  5. 使用CGContextStrokeRect();/ CGContextFillRect(); 画矩形
画三角形triangle
  1. 获取上下文件UIGraphicsGetCurrentContext();
  2. 设置起点,并连接三个点
  3. 关闭路径CGContextClosePath(ctx);
  4. 渲染CGContextStrokePath(ctx)
画圆circle

CGContextAddEllipseInRect(context, CGRectMake(10, 10, 100, 100));

画弧arc

//x y 圆点 //radius 半径 //startAngle 开始角度 //endAngle 结束角度 //clockwise 圆弧的伸展方向 0 顺时针 1 逆时针 void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise) CGContextAddArc(context, 100, 100, 50, 0, M_PI_2, 1);

画扇形sector

//设置扇形路径的起点 CGContextMoveToPoint(context, 100, 100); CGContextAddArc(context, 100, 100, 50, M_PI_4, 3 * M_PI_4, 0); CGContextClosePath(context);

UIBezierPath

使用UIBezierPath类可以创建基于矢量的路径,这个类在UIKit中。此类是Core Graphics框架关于path的一个封装。使用此类可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状。

Bezier Path 基础    UIBezierPath对象是CGPathRef数据类型的封装。path如果是基于矢量形状的,都用直线和曲线段去创建。我们使用直线段去创建矩形和多边形,使用曲线段去创建弧(arc),圆或者其他复杂的曲线形状。每一段都包括一个或者多个点,绘图命令定义如何去诠释这些点。每一个直线段或者曲线段的结束的地方是下一个的开始的地方。每一个连接的直线或者曲线段的集合成为subpath。一个UIBezierPath对象定义一个完整的路径包括一个或者多个subpaths。

iOS UIBezierPath贝塞尔曲线常用方法

CALayer

其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层。 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层 @property(nonatomic,readonly,retain) CALayer *layer;。 当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示。 UIView本身更像是一个CALayer的管理器。一个UIView上可以有n个CALayer,每个layer显示一种东西,增强UIView的展现能力。 对比CALayer,UIView多了一个事件处理的功能。所以,如果不需要跟用户进行交互,用UIView或者CALayer都可以。当然,CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级。 首先CALayer是定义在QuartzCore框架中的; CGImageRef、CGColorRef两种数据类型是定义在CoreGraphics框架中的; UIColor、UIImage是定义在UIKit框架中的; QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和Mac OS X上都能使用。 但是UIKit只能在iOS中使用为了保证可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef。 

CALayer的基本使用

  • 通过操作CALayer对象,可以很方便地调整UIView的一些外观属性,比如:阴影、圆角大小、边框宽度和颜色。
  • 还可以给图层添加动画,来实现一些比较炫酷的效果。

CALayer的属性

  • @property CGRect bounds; 宽度和高度;
  • @property CGPoint position; 位置(默认指中点,具体由anchorPoint决定)。用来设置CALayer在父层中的位置。以父层的左上角为原点(0, 0);
  • @property CGPoint anchorPoint;
    锚点(x,y的范围都是0-1),决定了position的含义。称为“定位点”、“锚点”决定着CALayer身上的哪个点会在position属性所指的位置以自己的左上角为原点(0, 0)它的x、y取值范围都是0~1,默认值为(0.5, 0.5)。
  • @property CGColorRef backgroundColor; 背景颜色(CGColorRef类型)
  • @property CATransform3D transform; 形变属性
  • @property CGColorRef borderColor; 边框颜色(CGColorRef类型)
  • @property CGFloat borderWidth; 边框宽度
  • @property GCFloat cornerRadius; 圆角半径
  • @property(retain) id contents; 内容(比如设置为图片CGImageRef)

UIView与CLayer有什么区别?

  1. UIView 是 iOS 系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由 CoreAnimation 来实现的。它真正的绘图部分,是由一个 CALayer 类来管理。 UIView 本身更像是一个 CALayer 的管理器,访问它的跟绘图和跟坐标有关的属性。
  2. UIView 有个重要属性 layer ,可以返回它的主 CALayer 实例。
  3. UIView 的 CALayer 类似 UIView 的子 View 树形结构,也可以向它的 layer 上添加子layer ,来完成某些特殊的表示。即 CALayer 层是可以嵌套的。
  4. UIView 的 layer 树形在系统内部,被维护着三份 copy 。分别是逻辑树,这里是代码可以操纵的;动画树,是一个中间层,系统就在这一层上更改属性,进行各种渲染操作;显示树,其内容就是当前正被显示在屏幕上得内容。
  5. 动画的运作:对 UIView 的 subLayer (非主 Layer )属性进行更改,系统将自动进行动画生成,动画持续时间的缺省值似乎是 0.5 秒。
  6. 坐标系统: CALayer 的坐标系统比 UIView 多了一个 anchorPoint 属性,使用CGPoint 结构表示,值域是 0~1 ,是个比例值。这个点是各种图形变换的坐标原点,同时会更改 layer 的 position 的位置,它的缺省值是 {0.5,0.5} ,即在 layer 的中央。
  7. 渲染:当更新层,改变不能立即显示在屏幕上。当所有的层都准备好时,可以调用setNeedsDisplay 方法来重绘显示。
  8. 变换:要在一个层中添加一个 3D 或仿射变换,可以分别设置层的 transform 或affineTransform 属性。
  9. 变形: Quartz Core 的渲染能力,使二维图像可以被自由操纵,就好像是三维的。图像可以在一个三维坐标系中以任意角度被旋转,缩放和倾斜。 CATransform3D 的一套方法提供了一些魔术般的变换效果。

CALayer的隐式动画

隐式动画每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)。所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画;

  • 什么是隐式动画? 当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果。这些属性称为Animatable Properties(可动画属性)。

  • 列举几个常见的Animatable Properties: bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画。
    backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画。
    position:用于设置CALayer的位置。修改这个属性会产生平移动画。

  • 可以通过动画事务(CATransaction)关闭默认的隐式动画效果

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    self.myview.layer.position = CGPointMake(10, 10);
    [CATransaction commit];