在 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;
}
}