CAAnimation 在 CALayer 上没有按预期工作
Posted
技术标签:
【中文标题】CAAnimation 在 CALayer 上没有按预期工作【英文标题】:CAAnimation not working as expected on CALayer 【发布时间】:2015-02-22 10:59:46 【问题描述】:我正在尝试为 CAShapeLayer
中的 UIBezierPath
的外观和消失设置动画。
我想做的是,在开始时,通过将 strokeStart
和 strokeEnd
设置为 0,路径将不可见。然后,在我的 animate
方法中,我将执行 CABasicAnimation
并设置strokeEnd
为 1,完成此操作后,另一个动画我将 strokeStart
设置为 1,因此路径将再次消失。这是我尝试过的:
- (void)animate
CAShapeLayer *layer = (CAShapeLayer *)self.layer;
CABasicAnimation *appearingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
appearingAnimation.duration = _duration / 2.0;
appearingAnimation.fromValue = @0;
appearingAnimation.toValue = @1;
CABasicAnimation *disappearingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
disappearingAnimation.beginTime = _duration / 2.0;
disappearingAnimation.duration = _duration / 2.0;
disappearingAnimation.fromValue = @0;
disappearingAnimation.toValue = @1;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.duration = _duration;
animationGroup.animations = @[appearingAnimation, disappearingAnimation];
animationGroup.repeatCount = MAXFLOAT;
[layer addAnimation:animationGroup forKey:@"test"];
但我看到的效果是appearingAnimation
工作正常,但是一旦完成,路径立即消失,没有任何动画。在此之后(_duration/2.0
时间之后)整个事情重新开始,所以看起来disappearingAnimation
没有效果。
我尝试了另一种方法,但只有当路径在我的view.layer
上时才有效。当我将它添加到子图层并尝试为那个子图层设置动画时,第二个(消失的)动画出现了故障。这是我的第二种方法:
- (void)animate
CAShapeLayer *layer = (CAShapeLayer *)self.layer;
layer.strokeStart = 0;
layer.strokeEnd = 1;
[CATransaction begin];
[CATransaction setCompletionBlock:^
layer.strokeStart = 1;
layer.strokeEnd = 1;
[CATransaction begin];
[CATransaction setCompletionBlock:^
[self animate];
];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
animation.duration = _duration / 2.0;
animation.fromValue = [NSNumber numberWithDouble:0];
animation.toValue = [NSNumber numberWithDouble:1];
[layer addAnimation:animation forKey:@"animation1"];
[CATransaction commit];
];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = _duration / 2.0;
animation.fromValue = [NSNumber numberWithDouble:0];
animation.toValue = [NSNumber numberWithDouble:1];
[layer addAnimation:animation forKey:@"animation"];
[CATransaction commit];
知道为什么第一个解决方案根本不起作用,或者为什么第二个解决方案只能在view.layer
而不是sublayer
上正常工作吗?
【问题讨论】:
【参考方案1】:在为图层属性设置动画时,您需要在添加动画之前将图层属性设置为结束值,因为动画更改仅应用于演示文稿,而不应用于模型图层。一旦动画完成,它将被移除,使图层保持之前的状态。
一旦创建了层(从您的 sn-p 中丢失),您概述的第一种和第二种方法都对我有用:
- (void)animate
CAShapeLayer *layer = [CAShapeLayer layer];
CGFloat _duration = 2.0;
CGFloat radius = self.view.frame.size.width/2.0;
CGFloat startAngle = -(M_PI_2);
CGFloat endAngle = (3*M_PI_2);
CGPoint center = CGPointMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0);
layer.path = [[UIBezierPath bezierPathWithArcCenter:center
radius:radius
startAngle:startAngle
endAngle:endAngle
clockwise:YES] CGPath];
layer.fillColor = [[UIColor clearColor] CGColor];
layer.strokeColor = [[UIColor blackColor] CGColor];
[self.view.layer addSublayer:layer];
... animation code
【讨论】:
【参考方案2】:我认为是_duration / 2.0
的值的问题。可能是浮点数计算的问题。
尽量不要将总时长减半,而是将appearingAnimation
和disappearingAnimation
的时长作为基础时长:
#define DURATION_BASE 1
// You can choose the DURATION_BASE value whaterver you like
- (void)animate
CAShapeLayer *layer = (CAShapeLayer *)self.layer;
CABasicAnimation *appearingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
appearingAnimation.duration = DURATION_BASE;
appearingAnimation.fromValue = @0;
appearingAnimation.toValue = @1;
CABasicAnimation *disappearingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
disappearingAnimation.beginTime = appearingAnimation.duration;
disappearingAnimation.duration = DURATION_BASE;
disappearingAnimation.fromValue = @0;
disappearingAnimation.toValue = @1;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.duration = appearingAnimation.duration+disappearingAnimation.duration;
animationGroup.animations = @[appearingAnimation, disappearingAnimation];
animationGroup.repeatCount = MAXFLOAT;
[layer addAnimation:animationGroup forKey:@"test"];
当你想改变appearingAnimation
和disappearingAnimation
的持续时间,你只需要修改代码
appearingAnimation.duration = DURATION_BASE*1.2;
disappearingAnimation.duration = DURATION_BASE*1.2;
【讨论】:
以上是关于CAAnimation 在 CALayer 上没有按预期工作的主要内容,如果未能解决你的问题,请参考以下文章
CALayer (CAAnimation) 动画属性绘制错误