• Core Animation和CALayer


    Animation Core想必大家都比较熟悉,是苹果一套针对动画效果的牛逼API,直接作用在layer上。今天打算扯扯这套API的某些细节,既然是作用在layer上那咱就先从layer开始扯起……

    一、CALayer

    1.1 什么是CALayer

    每个能在界面上看到的ui控件,其实都是因为这些ui控件里面有个layer层。这个层就是CALayer类,它有个很牛逼的方法:- (void)drawInContext:(CGContextRef)ctx;从这就能看出,当UIView需要显示的时候就会调用它进行绘图,绘图完毕后系统会把这个层拷贝到屏幕上就会被你look到。它还有个牛逼的方法:- (void)addAnimation:(CAAnimation *)anim forKey:(NSString *)key;这个就是跟Animation Core相关的方法,咱一会在看

    1.2 CALayer怎么用?(CALayer是定义在QuartzCore框架下的)

    /** Layer creation and initialization. **/
    
    + (instancetype)layer;
    
    /* The designated initializer. */
    
    - (instancetype)init;
    
    /* This initializer is used by CoreAnimation to create shadow copies of
     * layers, e.g. for use as presentation layers. Subclasses can override
     * this method to copy their instance variables into the presentation
     * layer (subclasses should call the superclass afterwards). Calling this
     * method in any other situation will result in undefined behavior. */
    
    - (instancetype)initWithLayer:(id)layer;
    View Code

    CALayer提供了这么多创建的方法。一个UIView默认会有一个Layer,但你可以手动添加其他的layer,可以设置或修改layer的属性改变起现实的样子。这些基础的东西直接贴段代码以示说明

    CALayer *customLayer=[CALayer layer];
        customLayer.bounds=CGRectMake(10, 10, 100, 100);
        
        customLayer.backgroundColor=[UIColor orangeColor].CGColor;
        
        //设置层中心点的位置(默认情况下中心点位置为0,0)
        customLayer.position=CGPointMake(100, 100);
        
        //设置圆角半径
        customLayer.cornerRadius=10;
        [self.view.layer addSublayer:customLayer];
    View Code

    也可以让我们自己创建的层现实具体的内容,比如一张图片(设置它的contents属性)customLayer.contents=(id)[UIImage imageNamed:@"fish"].CGImage;

    CGColorRef和UIColor以及CGImageRef和UIImage

    上文已经提醒过CALayer是定义在QuartzCore框架里,而CGImageRef、CGColor是定义在CoreGraphics框架里的,UIColor、UIImage是定义在UIKit框架里的。QuartzCore和CoreGraphics是可以跨平台的,在Mac和iOS上都能使用,但UIKit只能在iOS中使用,故而为了可移植性,QuartzCore只能使用CGImageRef、CGColor。undenstand?

    二、Core Animation

    2.1 Core Animation基本使用

    UIView *myView=[[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
        myView.layer.position=CGPointMake(100, 100);
        myView.backgroundColor=[UIColor orangeColor];
        self.myView=myView;
        [self.view addSubview:myView];
        
        CABasicAnimation *anim=[CABasicAnimation animationWithKeyPath:@"position"];
        anim.duration=1.5;
        anim.fromValue=[NSValue valueWithCGPoint:CGPointMake(50, 80)];
        anim.toValue=[NSValue valueWithCGPoint:CGPointMake(300, 350)];
        anim.delegate=self;
        anim.removedOnCompletion=NO;
        anim.fillMode=kCAFillModeForwards;
        [myView.layer addAnimation:anim forKey:@"translate"];
    View Code

    两个需要注意的属性:

      1、toValue表示移动到某个位置,如果换成byValue就成了移动了多少位置

      2、默认情况下,动画执行完毕后会回到初始的位置,为了保持移动后的状态,需要设置

      anim.removedOnCompletion=NO;

         anim.fillMode=kCAFillModeForwards;

    CABasicAnimation是CAPropertyAnimation的自类,CAPropertyAnimation又是CAAnimation的子类,在CAAnimation中,在这个父类中有个代理其中有两个代理方法

    - (void)animationDidStart:(CAAnimation *)anim;

    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

    可以用来监控运动的完成过程。在animationDidStop:方法中打印uiview当前的位置,可以看到与运动前的位置并没有改变。这是为什么呢?

    2.2 Core Animation维护两个layer

    这里需要说明的是当你把一个动画添加到layer时,是不直接修改它的属性的

    Core Animation维护了两个平行的layer层次结构:model layer tree和presentation layer tree(模型层树和表示层书树)。前者中的 layers 反映了我们能直接看到的 layers 的状态,而后者的 layers 则是动画正在表现的值的近似。

    /* Returns a copy of the layer containing all properties as they were

     * at the start of the current transaction, with any active animations

     * applied. This gives a close approximation to the version of the layer

     * that is currently displayed. Returns nil if the layer has not yet

     * been committed.

     *

     * The effect of attempting to modify the returned layer in any way is

     * undefined.

     *

     * The `sublayers', `mask' and `superlayer' properties of the returned

     * layer return the presentation versions of these properties. This

     * carries through to read-only layer methods. E.g., calling -hitTest:

     * on the result of the -presentationLayer will query the presentation

     * values of the layer tree. */

    - (id)presentationLayer;

    /* When called on the result of the -presentationLayer method, returns

     * the underlying layer with the current model values. When called on a

     * non-presentation layer, returns the receiver. The result of calling

     * this method after the transaction that produced the presentation

     * layer has completed is undefined. */

     - (id)modelLayer;

    上面说到默认情况下动画结束后会被移除,也就是说动画不会在超出起持续时间后还修改presentation layer,而是会彻底移除,一旦动画被移除presentation layer将回到model layer的值,并且动画过程中我们并未修改过position的值,所以你看到它又回到了原来的位置

    除了设置fillMode=kCAFillModeForward强制其留在最终状态并设置removedOnCompletion为NO以防止动画被自动移除外,还可以干脆就设置uiview的position为动画停止的position。

    还有一点不是很多人了解的是:如果将已完成的动画保持在layer上时,会造成额外的开销,因为渲染器会去进行额外的绘画工作。庆幸的是我们创建的动画对象被添加到layer时立刻就赋值了一份。这个特性在多个view中重用动画时非常有用。

    待续……

  • 相关阅读:
    GoGin 跨域处理
    Vue sso认证快速接入实践
    领域驱动设计(DDD):项目目录(包、模块)结构
    高绩效团队建设与管理系列课程
    VR设备产业链
    Supercell资深策划谈三大产品制作经验:游戏设计就像丛林探险,必须险中求胜
    领导力管理培训课
    博众投资:虚拟数字人概念,开辟元宇宙炒作新战场!
    FW: Flow区块链门票NFT开发实战【含源码】
    放弃学术研究,做投资大获成功
  • 原文地址:https://www.cnblogs.com/luseike/p/4335481.html
Copyright © 2020-2023  润新知