Slow down & accelerate animations with CoreAnimation
我正在尝试对我的应用程序应用慢动作效果,就像按 Shift 键可以减慢 Mac OS 的大多数图形效果一样。
我的应用程序使用 CoreAnimation,所以我认为它应该没什么大不了的:将
不幸的是,这似乎不是正确的方法。减速效果很好,但是当我想恢复正常速度时,它会恢复,就好像速度一直是
我找到了一个技术 QA 页面,解释了如何暂停和恢复动画,但如果不是完全暂停动画,我似乎无法正确理解。我绝对不擅长时间扭曲。
使用 CoreAnimation 放慢然后恢复动画的正确方法是什么?
这是有用的代码:
1 2 3 4 5 6 7 8 | -(void)flagsChanged:(NSEvent *)theEvent { CALayer* layer = self.layer; [CATransaction begin]; CATransaction.disableActions = YES; layer.speed = (theEvent.modifierFlags & NSShiftKeyMask) ? 0.1 : 1; [CATransaction commit]; } |
棘手的问题...
我用一个基本的 UIView 设置了一个测试。
我从它的当前点到目标点启动其层的动画。
为了减慢核心动画的速度,我实际上不得不构建和替换一个新的动画(因为你不能修改现有的动画)。
特别重要的是要弄清楚当前动画已经进行了多远。这是通过访问 beginTime、currentTime、计算经过的时间,然后计算出新动画的持续时间应该多长来完成的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | - (void)initiate { if(!initiated) { [CATransaction begin]; [CATransaction disableActions]; [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]]; CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"position"]; ba.duration = 10.0f; ba.fromValue = [NSValue valueWithCGPoint:view.layer.position]; ba.toValue = [NSValue valueWithCGPoint:CGPointMake(384, 512)]; [view.layer addAnimation:ba forKey:@"animatePosition"]; [CATransaction commit]; initiated = YES; } } - (void)slow { [CATransaction begin]; CABasicAnimation *old = (CABasicAnimation *)[view.layer animationForKey:@"animatePosition"]; CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"position"]; CFTimeInterval animationBegin = old.beginTime; CFTimeInterval currentTime = CACurrentMediaTime(); CFTimeInterval elapsed = currentTime - animationBegin; ba.duration = [[old valueForKey:@"duration"] floatValue] - elapsed; ba.duration = [[old valueForKey:@"duration"] floatValue]; ba.autoreverses = [[old valueForKey:@"autoreverses"] boolValue]; ba.repeatCount = [[old valueForKey:@"repeatCount"] floatValue]; ba.fromValue = [NSValue valueWithCGPoint:((CALayer *)[view.layer presentationLayer]).position]; ba.toValue = [old valueForKey:@"toValue"]; ba.speed = 0.1; [view.layer addAnimation:ba forKey:@"animatePosition"]; [CATransaction commit]; } - (void)normal { [CATransaction begin]; CABasicAnimation *old = (CABasicAnimation *)[view.layer animationForKey:@"animatePosition"]; CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"position"]; CFTimeInterval animationBegin = old.beginTime; CFTimeInterval currentTime = CACurrentMediaTime(); CFTimeInterval elapsed = currentTime - animationBegin; ba.duration = [[old valueForKey:@"duration"] floatValue] - elapsed; ba.autoreverses = [[old valueForKey:@"autoreverses"] boolValue]; ba.repeatCount = [[old valueForKey:@"repeatCount"] floatValue]; ba.fromValue = [NSValue valueWithCGPoint:((CALayer *)[view.layer presentationLayer]).position]; ba.toValue = [old valueForKey:@"toValue"]; ba.speed = 1; [view.layer addAnimation:ba forKey:@"animatePosition"]; [CATransaction commit]; } |
注意:以上代码仅适用于 1 个方向,不适用于自动反转的动画...