美文网首页
iOS 动画过程中获取实时变化的属性值

iOS 动画过程中获取实时变化的属性值

作者: 奋进的小时光_Joe | 来源:发表于2018-11-02 19:31 被阅读50次

    该本仅为笔者自己的理解,如果有不正确的地方,请不吝指教。

    当你在实现某个动画效果是,如果想要监听到当前 view 或者 layer 在动画过程中属性的时,可以通过CALayer 的presentationLayer方法来进行获取。

    CALayer 中有一个很有意思的方法:

    - (nullable instancetype)presentationLayer;
    

    CALayer中包含了一个presentationLayer表示层和modelLayer模型层

    如果你对 layer 添加一个animation动画,当动画开始以后,layer的属性其实并没有发行变化,变化的只是 layer 中表示presentationLayer的属性,所有要获取在动画过程中 layer 的属性,可以通过下面的方式获取

    @interface ViewController ()<CAAnimationDelegate>{
        //CADisplayLink本质就是一个和屏幕内容更新同频率的定时器
        CADisplayLink *displayLink;
    }
    @property (weak, nonatomic) IBOutlet UIView *redView;
    @property (nonatomic, strong) CALayer *layer;
    @end
    
    @implementation ViewController
    
    - (CADisplayLink *)getDisplayLink{
    
        if (!displayLink) {
            //初始化 displayLink
            displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLink)];
            //将 displayLink 添加到 RunLoop 中
            [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
        }
    
        return displayLink;
    }
    
    - (void)removeDisplayLink{
        
        [displayLink invalidate];
        displayLink = nil;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onRedView)];
        [self.redView addGestureRecognizer:tap];
    }
    
    - (void)onRedView{
        
        NSLog(@"-----red view 被点击了");
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        //给 redView 添加一个在y轴移动的动画
        CABasicAnimation *anim = [CABasicAnimation animation];
        anim.keyPath = @"position.y";
        anim.toValue = @400;
        anim.removedOnCompletion = NO;
        anim.fillMode = kCAFillModeForwards;
        anim.delegate = self;
        [_redView.layer addAnimation:anim forKey:nil];
    }
    
    #pragma mark - CAAnimationDelegate
    
    - (void)displayLink{
    
        NSLog(@"\nprsention.frame - %@\nmodel.frame - %@\nlayer.frame - %@",NSStringFromCGRect(_redView.layer.presentationLayer.frame), NSStringFromCGRect(_redView.layer.modelLayer.frame), NSStringFromCGRect(_redView.layer.frame));
    }
    //动画开始
    - (void)animationDidStart:(CAAnimation *)anim{
        NSLog(@"start-%@",NSStringFromCGRect(_redView.frame));
        [self getDisplayLink];
    }
    
    //动画结束
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
        //    NSLog(@"stop-%@",NSStringFromCGRect(_redView.frame));
        NSLog(@"stop-%@",NSStringFromCGRect(_redView.layer.presentationLayer.frame));
        [self removeDisplayLink];
    }
    

    输出打印结果:

    2018-11-02 19:13:22.783428+0800 基础动画[11216:1254495] start-{{0, 20}, {100, 100}}
    2018-11-02 19:13:22.784029+0800 基础动画[11216:1254495] 
    prsention.frame - {{0, 20.95416596159339}, {100, 100}}
    model.frame - {{0, 20}, {100, 100}}
    layer.frame - {{0, 20}, {100, 100}}
    2018-11-02 19:13:22.787055+0800 基础动画[11216:1254495] -----red view 被点击了
    2018-11-02 19:13:22.800747+0800 基础动画[11216:1254495] 
    prsention.frame - {{0, 43.088731914758682}, {100, 100}}
    model.frame - {{0, 20}, {100, 100}}
    layer.frame - {{0, 20}, {100, 100}}
    ……
    2018-11-02 19:13:23.017459+0800 基础动画[11216:1254495] 
    prsention.frame - {{0, 329.13446128368378}, {100, 100}}
    model.frame - {{0, 20}, {100, 100}}
    layer.frame - {{0, 20}, {100, 100}}
    2018-11-02 19:13:23.033881+0800 基础动画[11216:1254495] 
    prsention.frame - {{0, 349.99868214130402}, {100, 100}}
    model.frame - {{0, 20}, {100, 100}}
    layer.frame - {{0, 20}, {100, 100}}
    2018-11-02 19:13:23.034101+0800 基础动画[11216:1254495] stop-{{0, 349.99868214130402}, {100, 100}}
    

    从打印结果可以看出,layer的位置其实是一直没有发生变化的,View 的位置当然也没有,在动画结束后点击移动过的红色 view 的位置其实并不会响应在 view 上添加的 tag 方法,view 的位置其实还是在之前的位置,移动的位置只是 layer 的表现层的 frame。

    复杂的动画效果都是通过多种基本的动画组合行程的,比如说通过获取两个不同动画时间的 view 的位移动画,就可以实时的获取到他们之间的一组差值,利用这个差值来再来做一些曲线的变化之类的动画效果就很方便啦。

    如果感觉有帮助的话,请点一个喜欢!

    相关文章

      网友评论

          本文标题:iOS 动画过程中获取实时变化的属性值

          本文链接:https://www.haomeiwen.com/subject/jtacxqtx.html