CAShaperLayer的BezierPath动画

在做业务需求的通常会有一些异形图片,我们通常会使用CAShaperLayer来绘制这些图形,因为他比较简单且易维护,但是有时候会遇到一些bezierPath的动画,这个时候往往就会出现各种奇怪的动画效果,比如美团外卖的tab,如果为了快速完成需求,可以直接用lottie实现,可是身为iOSer,总是希望可以用原生实现这样的功能。

接下来我们就用代码实现这个功能,首先画个路径:

   CGFloat height = 100;
    NSInteger itemCount = 5;
    CGFloat itemWidth = [UIScreen width]/itemCount;
    CGFloat topSpace = 25;
    CGFloat s = 82.945 / 180.0 * M_PI;
    __block CAShapeLayer *layer1;
    UIBezierPath *bezierPath = [UIBezierPath bezierPath];
    [bezierPath moveToPoint:CGPointMake(0, topSpace)];
    [bezierPath addLineToPoint:CGPointMake(itemWidth * 2 - 3.5, topSpace)];
    [bezierPath addArcWithCenter:CGPointMake([UIScreen width]/2, topSpace + 3.5) radius:28.5  startAngle:(3 * M_PI_2 - s) endAngle: (M_PI_2 * 3 + s) clockwise:YES];
    [bezierPath addLineToPoint:CGPointMake([UIScreen width], topSpace)];
    [bezierPath addLineToPoint:CGPointMake([UIScreen width], height)];
    [bezierPath addLineToPoint:CGPointMake(0, height)];
    [bezierPath addLineToPoint:CGPointMake(0, topSpace)];
    CAShapeLayerCreate().makeChain.frame(CGRectMake((0) /2, ([UIScreen height] - 200) /2, [UIScreen width], 200))
    .shadowColor([UIColor blackColor].CGColor)
    .shadowRadius(4)
    .path(bezierPath.CGPath)
    .lineWidth(1)
    .fillColor([UIColor yellowColor].CGColor)
    .borderColor(UIColor.redColor.CGColor)
    .borderWidth(1)
    .strokeColor(UIColor.blackColor.CGColor)
    .backgroundColor([UIColor clearColor].CGColor)
    .addToSuperLayer(self.view.layer)
    .assignTo(^(__kindof CALayer * _Nonnull layer) {
        layer1 = layer;
    });
image.png

然后画个动画后的路径:

         UIBezierPath *bezierPath = [UIBezierPath bezierPath];
        [bezierPath moveToPoint:CGPointMake(0, topSpace)];
        [bezierPath addLineToPoint:CGPointMake(itemWidth * 2 - 3.5, topSpace)];
        [bezierPath addLineToPoint:bezierPath.currentPoint];
        [bezierPath addLineToPoint:CGPointMake([UIScreen width]/2, topSpace)];
        [bezierPath addLineToPoint:CGPointMake(itemWidth * 3 + 3.5, topSpace)];
        [bezierPath addLineToPoint:CGPointMake([UIScreen width], topSpace)];
        [bezierPath addLineToPoint:CGPointMake([UIScreen width], height)];
        [bezierPath addLineToPoint:CGPointMake(0, height)];
        [bezierPath addLineToPoint:CGPointMake(0, topSpace)];
image.png

接下来添加一个动画:

        CASpringAnimation *animated = [CASpringAnimation animationWithKeyPath:@"path"];
        animated.fromValue = (id)(layer1.path);
        animated.toValue = (id)(bezierPath.CGPath);
        animated.removedOnCompletion = NO;
        animated.fillMode = kCAFillModeForwards;
        animated.duration = 1;
        animated.mass = 1;
        [layer1 addAnimation:animated forKey:@"path"];

接下来我们就可以看到这个动画的效果了:

好吧,我承认跟lottie的还是有点差距,不过我想说的是当一个不规则path向规则path做动画的时候其实更多地是保持path段的一致性,不一致就会发生错乱动画,比如之前的突起形状有7段,而方形有9段,这是因为如果我们打断点看这个path,会发现:


在实际的path中,addArcWithCenter:会向path添加两段,当他们的段数一样的话,用动画来过度就会表现的非常平滑。

你可能感兴趣的:(CAShaperLayer的BezierPath动画)