我们经常使用CABasicAnimation实现动画效果,如果要观察动画实现时候的值,应该怎么实现呢?
1.使用KVO,提示被观察者在observer被释放之前就释放了.
2.使用NSTimer,NSTimer有间隔不稳定的问题.
3.使用CADisplayLink
CADisplayLink
是一个定时器.和NSTimer
不同的是,它是和屏幕的刷新率相同的,比较准确.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var animation = CASpringAnimation() animation.keyPath = "position.y" animation.fromValue = animatingItem!.layer.position.y - itemSpace - itemSize animation.toValue = animatingItem!.layer.position.y animation.duration = animation.settlingDuration animation.mass = 1 animation.stiffness = 200 animation.damping = 10 animation.initialVelocity = 0 animatingItem?.layer.hidden = false displayLink = CADisplayLink(target: self, selector: "printItemPosition") displayLink!.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes) CATransaction .begin() CATransaction.setCompletionBlock { [weak self] in self!.displayLink!.paused = true self!.displayLink!.invalidate() } animatingItem?.layer.addAnimation(animation, forKey: "basic") CATransaction.commit()
|
1 2 3
| func printItemPosition(){ print(self.animatingItem!.layer.presentationLayer()!.position.y) }
|
使用CADisplayLink精确控制动画
以下这个动画效果为:当一个item的位置下降到一定位置时,触发下一个item的动画效果.
我的第一个想法是使用UIView的addAnimation方法,并且设置completion,但是发现CASpringAnimation是layer层的,和UIVew的addAnimation方法不兼容.接下来想到使用CATransaction的setCompletionBlock方法,发现和设想中的效果有偏差:CASpringAnimation的持续时间包括缓慢停止的时间,这样设置并不能达到流畅下落的效果.最后尝试使用CADisplayLink,观察正在下落的item的presentationLayer的position,当item到达一定的position,触发下一个item的动画.
代码见github