How to make my UIBezierPath animated with CAShapeLayer?

假装没事ソ 提交于 2019-11-27 12:51:57

It looks like you're trying to animate within drawRect (indirectly, at least). That doesn't quite make sense. You don't animate within drawRect. The drawRect is used for drawing a single frame. Some animation is done with timers or CADisplayLink that repeatedly calls setNeedsDisplay (which will cause iOS to call your drawRect) during which you might draw the single frame that shows the progress of the animation at that point. But you simply don't have drawRect initiating any animation on its own.

But, since you're using Core Animation's CAShapeLayer and CABasicAnimation, you don't need a custom drawRect at all. Quartz's Core Animation just takes care of everything for you. For example, here is my code for animating the drawing of a UIBezierPath:

#import <QuartzCore/QuartzCore.h>

@interface View ()
@property (nonatomic, weak) CAShapeLayer *pathLayer;
@end

@implementation View

/*
// I'm not doing anything here, so I can comment this out
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}
*/

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

// It doesn't matter what my path is. I could make it anything I wanted.

- (UIBezierPath *)samplePath
{
    UIBezierPath *path = [UIBezierPath bezierPath];

    // build the path here

    return path;
}

- (void)startAnimation
{
    if (self.pathLayer == nil)
    {
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];

        shapeLayer.path = [[self samplePath] CGPath];
        shapeLayer.strokeColor = [[UIColor grayColor] CGColor];
        shapeLayer.fillColor = nil;
        shapeLayer.lineWidth = 1.5f;
        shapeLayer.lineJoin = kCALineJoinBevel;

        [self.layer addSublayer:shapeLayer];

        self.pathLayer = shapeLayer;
    }

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    pathAnimation.duration = 3.0;
    pathAnimation.fromValue = @(0.0f);
    pathAnimation.toValue = @(1.0f);
    [self.pathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
}

@end

Then, when I want to start drawing the animation, I just call my startAnimation method. I probably don't even need a UIView subclass at all for something as simple as this, since I'm not actually changing any UIView behavior. There are definitely times that you subclass UIView with a custom drawRect implementation, but it's not needed here.

You asked for some references:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!