我想创建这样的东西,只考虑单循环以及它如何完成一个圆并在完成时反转它:
这段代码完成了我想要的一半:
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
drawAnimation.duration = 1;
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue = [NSNumber numberWithFloat:1.0f];
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[circleLayer addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
我尝试将其反转但不起作用:
[CATransaction begin];
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
drawAnimation.duration = 1;
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue = [NSNumber numberWithFloat:1.0f];
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//[circleLayer addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
[CATransaction setCompletionBlock:^{
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation2.duration = 1;
animation2.fromValue = [NSNumber numberWithFloat:0.0f];
animation2.toValue = [NSNumber numberWithFloat:1.0f];
animation2.removedOnCompletion = NO;
animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[circleLayer addAnimation:animation2 forKey:@"circelBack"];
}];
[circleLayer addAnimation:drawAnimation forKey:@"circleFront"];
[CATransaction commit];
问题是我无法逆转动画。
答案 0 :(得分:1)
首先,我怀疑你是否以错误的方式获得了动画的关键路径。您应该首先将笔画结束从0设置为1,然后然后笔画从0开始为1。
其次,您永远不会使用新值更新模型图层 - 因此,当动画完成后,图层将会快速恢复'到原来的状态。对你而言,这意味着当第一个动画完成时 - strokeStart
将快照回0.0
- 因此反向动画看起来很奇怪。
要更新模型图层值,您只需在disableActions
块中将YES
设置为CATransaction
即可防止在图层属性更改时生成隐式动画(赢得'影响显式动画)。然后,您希望在将动画添加到图层后更新模型图层的属性。
此外,您可以重复使用CAAnimations - 因为它们在添加到图层时会被复制。因此,您可以为正向和反向动画定义相同的动画,只需更改关键路径。
如果你重复动画,你可能想要将动画定义为ivar - 只需在添加动画之前更新它。
例如,在您的viewDidLoad
:
@implementation ViewController {
CABasicAnimation* drawAnimation;
}
- (void)viewDidLoad {
[super viewDidLoad];
// define your animation
drawAnimation = [CABasicAnimation animation];
drawAnimation.duration = 1;
// use an NSNumber literal to make your code easier to read
drawAnimation.fromValue = @(0.0f);
drawAnimation.toValue = @(1.0f);
// your timing function
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
// kick off the animation loop
[self animate];
}
然后,您想创建一个animate
方法,以便执行动画的一次迭代。不幸的是,由于Core Animation不支持在序列中重复多个动画,因此您必须使用递归来实现您的效果。
例如:
-(void) animate {
if (self.circleLayer.superlayer) { // check circle layer is the layer heirachy before attempting to animate
// begin your transaction
[CATransaction begin];
// prevent implicit animations from being generated
[CATransaction setDisableActions:YES];
// reset values
self.circleLayer.strokeEnd = 0.0;
self.circleLayer.strokeStart = 0.0;
// update key path of animation
drawAnimation.keyPath = @"strokeEnd";
// set your completion block of forward animation
[CATransaction setCompletionBlock:^{
// weak link to self to prevent a retain cycle
__weak typeof(self) weakSelf = self;
// begin new transaction
[CATransaction begin];
// prevent implicit animations from being generated
[CATransaction setDisableActions:YES];
// set completion block of backward animation to call animate (recursive)
[CATransaction setCompletionBlock:^{
[weakSelf animate];
}];
// re-use your drawAnimation, just changing the key path
drawAnimation.keyPath = @"strokeStart";
// add backward animation
[weakSelf.circleLayer addAnimation:drawAnimation forKey:@"circleBack"];
// update your layer to new stroke start value
weakSelf.circleLayer.strokeStart = 1.0;
// end transaction
[CATransaction commit];
}];
// add forward animation
[self.circleLayer addAnimation:drawAnimation forKey:@"circleFront"];
// update layer to new stroke end value
self.circleLayer.strokeEnd = 1.0;
[CATransaction commit];
}
}
要停止动画,您可以从超级图层中删除图层 - 或者实现您自己的布尔检查以确定动画是否应该继续。