Animating a bezier curve point

2019-02-11 07:33发布

问题:

I'm trying to animate a bezier curve I made with Paintcode (great app, btw) and am drawing in a custom UIView in the "drawRect" method.

The drawing works fine but I want to animate a single point in the bezier curve.

Here's my non-working method:

-(void)animateFlame{
    NSLog(@"Animating");
    // Create the starting path. Your curved line.
    //UIBezierPath * startPath;
    // Create the end path. Your straight line.
    //UIBezierPath * endPath = [self generateFlame];
    //[endPath moveToPoint: CGPointMake(167.47, 214)];

    int displacementX = (((int)arc4random()%50))-25;
    int displacementY = (((int)arc4random()%30))-15;
    NSLog(@"%i %i",displacementX,displacementY);

    UIBezierPath* theBezierPath = [UIBezierPath bezierPath];
    [theBezierPath moveToPoint: CGPointMake(167.47, 214)];
    [theBezierPath addCurveToPoint: CGPointMake(181+displacementX, 100+displacementY) controlPoint1: CGPointMake(89.74, 214) controlPoint2: CGPointMake(192.78+displacementX, 76.52+displacementY)];
    [theBezierPath addCurveToPoint: CGPointMake(167.47, 214) controlPoint1: CGPointMake(169.22+displacementX, 123.48+displacementY) controlPoint2: CGPointMake(245.2, 214)];
    [theBezierPath closePath];
    // Create the shape layer to display and animate the line.
    CAShapeLayer * myLineShapeLayer = [[CAShapeLayer alloc] init];

    CABasicAnimation * pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
    pathAnimation.fromValue = (__bridge id)[bezierPath CGPath];
    pathAnimation.toValue = (__bridge id)[theBezierPath CGPath];
    pathAnimation.duration = 0.39f;
    [myLineShapeLayer addAnimation:pathAnimation forKey:@"pathAnimation"];

    bezierPath = theBezierPath;
}

Using this, nothing moves on the screen at all. The random displacements generated are good and the bezierPath variable is a UIBezierPath that's declared with a class scope.

Am I missing something? (The goal is to do a sort of candle-like animation)

回答1:

Quick Edit Just seen your layer code. You are mixing up several different concepts. Like drawRect, CAShapeLayer, old animation code etc...

By doing the method below you should be able to get this working.

You can't do this :( you can't animate the contents of drawRect (i.e. you can't get it to draw multiple times over the course of the animation).

You may be able to use a timer or something and create your own animation type code. (i.e. create a timer that fires 30 times a second and runs a function that calculates where you are in the animation and updates the values you want to change and calls [self setNeedsDisplay]; to trigger the draw rect method.

Other than that there isn't much you can do.

ANOTHER EDIT

Just adding another option here. Doing this with a CAShapeLayer might be very poor performance. You might be best using a UIImageView with a series of UIImages.

There are built in properties, animationImages, animationDuration, etc... on UIImageView.

POSSIBLE SOLUTION

The path property of CAShapeLayer is animatable and so you could possible use this.

Something like...

// set up properties for path
@property (nonatomic, assign) CGPath startPath;
@property (nonatomic, assign) CGPath endPath;
@property (nonatomic, strong) CAShapeLayer *pathLayer;

// create the startPath
UIBezierPath *path = [UIBezierPath //create your path using the paint code code
self.startPath = path.CGPath;

// create the end path
path = [UIBezierPath //create your path using the paint code code
self.endPath = path.CGPath;

// create the shapee layer
self.pathLayer = [CAShapeLayer layer];
self.pathLayer.path = self.startPath;
//also set line width, colour, shadows, etc...

[self.view.layer addSubLayer:self.pathLayer];

Then you should be able to animate the path like this...

- (void)animatePath
{
    [UIView animateWithDuration:2.0
        animations^() {
            self.pathlayer.path = self.endPath;
    }];
}

There are lots of notes in the docs about CAShapeLayer and animating the path property.

This should work though.

Also, get rid of the old animation code. It has been gone since iOS4.3 you should be using the updated block animations.