CAShapeLayer的CABasicAnimation在完成之前消失,并且不会无限延续

时间:2016-12-25 04:27:26

标签: ios objective-c core-graphics core-animation calayer

我正在尝试创建一个绘制的无限跟踪路径,它的背面消失。但是,我的代码使路径在单次迭代后消失。实际上,在路径消失动画完成之前,图层会消失。相反,它似乎在绘图动画完成时消失。

此外,一旦它消失,它再次开始之前不会再显示几秒钟(可能需要很长时间才能重复动画)。

两个问题:

  1. 为什么在消失的动画完成之前图层会消失?

  2. 如何让动画连续播放而不会消失?

  3. 提前谢谢!这是我的代码:

    CGRect boundingFrame = CGRectMake(CGRectGetMidX(self.bounds) - 48.0, CGRectGetMidY(self.bounds) - 48.0, 96.0, 96.0);
    
    _pathPoints = @[
                     [NSValue valueWithCGPoint:CGPointMake(CGRectGetMidX(boundingFrame), CGRectGetMinY(boundingFrame) + squareSideWidth/2.0)],
                     [NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(boundingFrame) + squareSideWidth/2.0, CGRectGetMidY(boundingFrame))],
                     [NSValue valueWithCGPoint:CGPointMake(CGRectGetMidX(boundingFrame), CGRectGetMaxY(boundingFrame) - squareSideWidth/2.0)],
                     [NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(boundingFrame) - squareSideWidth/2.0, CGRectGetMidY(boundingFrame))]
                    ];
    
    CAShapeLayer *line = [CAShapeLayer layer];
    line.path = pathForPoints(_pathPoints).CGPath;
    line.lineCap = kCALineCapRound;
    line.strokeColor = color.CGColor;
    line.fillColor = [UIColor clearColor].CGColor;
    line.strokeEnd = 0.0;
    [self.layer addSublayer:line];
    
    NSMutableArray<CABasicAnimation *> *animations = [NSMutableArray new];
    for (int i = 0; i < [_pathPoints count]; i++) {
        CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        drawAnimation.beginTime = index;
        drawAnimation.duration = 1.0;
        drawAnimation.fromValue = @(strokeEndForIndex(points, index - 1));
        drawAnimation.toValue = @(strokeEndForIndex(points, index));
        drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        drawAnimation.additive = YES;
        drawAnimation.removedOnCompletion = NO;
    
        CABasicAnimation *eraseAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
        eraseAnimation.beginTime = index + 0.75;
        eraseAnimation.duration = 1.0;
        eraseAnimation.fromValue = @(strokeEndForIndex(points, index - 1));
        eraseAnimation.toValue = @(strokeEndForIndex(points, index));
        eraseAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        eraseAnimation.additive = YES;
        eraseAnimation.removedOnCompletion = NO;
    
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.animations = @[drawAnimation, eraseAnimation];
        group.duration = 2.0 * [animations count];
        group.repeatCount = INFINITY;
        group.removedOnCompletion = NO;
        [line addAnimation:group forKey:@"line"];
    }
    

    辅助函数,供参考:

    static CGFloat lengthOfPathWithPoints(NSArray<NSValue *> *points)
    {
        CGFloat totalDist = 0;
        for (int i = 0; i < [points count]; i++) {
            CGFloat xDist = [points[i % [points count]] CGPointValue].x - [points[(i + 1) % [points count]] CGPointValue].x;
            CGFloat yDist = [points[i % [points count]] CGPointValue].y - [points[(i + 1) % [points count]] CGPointValue].y;
            totalDist += sqrt(pow(xDist, 2) + pow(yDist, 2));
        }
        return totalDist;
    }
    
    static CGFloat strokeEndForIndex(NSArray<NSValue *> *points, int index)
    {
        // If it's the last index, just return 1 early
        if (index == [points count] - 1) {
            return 1.0;
        }
        // In the case where index = -1 (as it does for the initial erase animation fromValue), just return 0
        if (index < 0) {
            return 0.0;
        }
    
        CGFloat totalDist = 0;
        for (int i = 0; i < index + 1; i++) {
            CGFloat xDist = [points[i % [points count]] CGPointValue].x - [points[(i + 1) % [points count]] CGPointValue].x;
            CGFloat yDist = [points[i % [points count]] CGPointValue].y - [points[(i + 1) % [points count]] CGPointValue].y;
            totalDist += sqrt(pow(xDist, 2) + pow(yDist, 2));
        }
    
        return totalDist/lengthOfPathWithPoints(points);
    }
    
    static UIBezierPath *pathForPoints(NSArray<NSValue *> *points)
    {
        UIBezierPath *path = [UIBezierPath new];
        [path moveToPoint:[[points firstObject] CGPointValue]];
        for (int i = 0; i < [points count]; i++) {
            [path addLineToPoint:[points[(i + 1) % 4] CGPointValue]];
        }
        return path;
    }
    

1 个答案:

答案 0 :(得分:0)

增加持续时间属性值并将repeatCount = Float(Int.max)更改为此类似值。