How to do a curve/arc animation with CAAnimation?

前端 未结 5 667
离开以前
离开以前 2021-01-30 09:35

I have an user interface where an item get deleted, I would like to mimic the \"move to folder\" effect in iOS mail. The effect where the little letter icon is \"thrown\" into t

5条回答
  •  遥遥无期
    2021-01-30 10:17

    You are absolutely correct that animating the position with a CABasicAnimation causes it to go in a straight line. There is another class called CAKeyframeAnimation for doing more advanced animations.

    An array of values

    Instead of toValue, fromValue and byValue for basic animations you can either use an array of values or a complete path to determine the values along the way. If you want to animate the position first to the side and then down you can pass an array of 3 positions (start, intermediate, end).

    CGPoint startPoint = myView.layer.position;
    CGPoint endPoint   = CGPointMake(512.0f, 800.0f); // or any point
    CGPoint midPoint   = CGPointMake(endPoint.x, startPoint.y);
    
    CAKeyframeAnimation *move = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    move.values = @[[NSValue valueWithCGPoint:startPoint],
                    [NSValue valueWithCGPoint:midPoint],
                    [NSValue valueWithCGPoint:endPoint]];
    move.duration = 2.0f;
    
    myView.layer.position = endPoint; // instead of removeOnCompletion
    [myView.layer addAnimation:move forKey:@"move the view"];
    

    If you do this you will notice that the view moves from the start point in a straight line to the mid point and in another straight line to the end point. The part that is missing to make it arc from start to end via the mid point is to change the calculationMode of the animation.

    move.calculationMode = kCAAnimationCubic;
    

    You can control it arc by changing the tensionValues, continuityValues and biasValues properties. If you want finer control you can define your own path instead of the values array.

    A path to follow

    You can create any path and specify that the property should follow that. Here I'm using a simple arc

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL,
                      startPoint.x, startPoint.y);
    CGPathAddCurveToPoint(path, NULL,
                          controlPoint1.x, controlPoint1.y,
                          controlPoint2.x, controlPoint2.y,
                          endPoint.x, endPoint.y);
    
    CAKeyframeAnimation *move = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    move.path = path;
    move.duration = 2.0f;
    
    myView.layer.position = endPoint; // instead of removeOnCompletion
    [myView.layer addAnimation:move forKey:@"move the view"];
    

提交回复
热议问题