iOS 自定义动画曲线 CAMediaTimingFunction

250 阅读2分钟

在 iOS 开发中,自定义动画曲线可以通过 CAMediaTimingFunction 来实现,这是一种能够定义动画的节奏(缓动)的工具。它允许开发者使用贝塞尔曲线,通过四个控制点细致地调整动画的加速和减速。

使用 CAMediaTimingFunction

CAMediaTimingFunction 使用贝塞尔曲线来描述动画的进度,曲线由两个控制点定义:P1(x1, y1)和 P2(x2, y2)。起始点(0, 0)和终点(1, 1)是固定的。

创建自定义 CAMediaTimingFunction

可以通过 functionWithControlPoints:::: 方法定义自定义曲线。这使得可以精准调整动画的起伏和缓动效果。

CAMediaTimingFunction *customTimingFunction = [CAMediaTimingFunction functionWithControlPoints:0.25f :0.8f :0.75f :0.2f];

将自定义的 CAMediaTimingFunction 应用于 CABasicAnimation 或 CAKeyframeAnimation。以下是一个示例:

// 创建基础动画
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(300, 300)];
animation.duration = 2.0;

// 使用自定义的 Timing Function
animation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.25 :0.1 :0.25 :1.0];

// 将动画添加到视图的层中
[view.layer addAnimation:animation forKey:@"customMoveAnimation"];

分析控制点

(x1, y1) 和 (x2, y2): 控制动画的加速模式。通过调整这两个点,你可以影响动画在不同阶段的速度变化。
x 值影响动画速率的比例,值在 0.0 到 1.0 之间。
y 值影响动画的进度比例,也是 0.0 到 1.0。

更复杂的动画路径:CAKeyframeAnimation

如果需要更为复杂的路径动画,还可以与 CAKeyframeAnimation 结合使用:

CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
keyframeAnimation.duration = 3.0;

// 定义路径
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(50, 50)];
[path addCurveToPoint:CGPointMake(300, 300) controlPoint1:CGPointMake(150, 200) controlPoint2:CGPointMake(250, 100)];

keyframeAnimation.path = path.CGPath;
keyframeAnimation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.5 :1.5 :0.5 :0.5];

// 将动画添加到图层
[view.layer addAnimation:keyframeAnimation forKey:@"customPathAnimation"];
- (void)setAngle:(CGFloat)angle forHand:(UIView *)handView animated:(BOOL)animated
{
    //generate transform
    CATransform3D transform = CATransform3DMakeRotation(angle, 0, 0, 1);
    if (animated) {
        //create transform animation
        CABasicAnimation *animation = [CABasicAnimation animation];
        animation.keyPath = @"transform";
        animation.fromValue = [handView.layer.presentationLayer valueForKey:@"transform"];
        animation.toValue = [NSValue valueWithCATransform3D:transform];
        animation.duration = 0.5;
        animation.delegate = self;
        animation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:1 :0 :0.75 :1];
        //apply animation
        handView.layer.transform = transform;
        [handView.layer addAnimation:animation forKey:nil];
    } else {
        //set transform directly
        handView.layer.transform = transform;
    }
}