我正试图在UIBezierPath
中为CAShapeLayer
的外观和消失设置动画。
我希望如何做到这一点,一开始,通过将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
上正常工作?
答案 0 :(得分:0)
在设置图层属性的动画时,您需要在添加动画之前将图层属性设置为结束值,因为动画更改仅应用于演示文稿,而不是模型图层。动画完成后,它将被移除,使图层处于之前的状态。
创建图层后,您概述的第一种和第二种方法都适用于我(从您的代码段中遗漏):
- (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}
}
答案 1 :(得分:0)
我认为这是_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;