gpt4 book ai didi

iphone - 如何使用 Core Animation 创建自定义缓动函数?

转载 作者:行者123 更新时间:2023-12-03 18:08:16 24 4
gpt4 key购买 nike

我在 iOS 中很好地沿着 CGPath (QuadCurve) 制作 CALayer 动画。但我想使用比少数几个更有趣的缓动函数 provided由苹果公司(EaseIn/EaseOut 等)。例如,弹跳或弹性函数。

这些事情可以用 MediaTimingFunction (bezier) 来做:

enter image description here

但我想创建更复杂的计时函数。问题是媒体定时似乎需要三次贝塞尔曲线,但它的强度不足以产生这些效果:

enter image description here
(来源:sparrow-framework.org)

code在其他框架中创建上述内容非常简单,这使得这非常令人沮丧。请注意,这些曲线是将输入时间映射到输出时间(T-t 曲线),而不是时间-位置曲线。例如,easeOutBounce(T) = t 返回一个新的t。然后,t 用于绘制运动(或我们应该设置动画的任何属性)。

所以,我想创建一个复杂的自定义 CAMediaTimingFunction 但我不知道如何做到这一点,或者是否可能?还有其他选择吗?

编辑:

这是步骤的具体示例。非常有教育意义:)

  1. 我想要沿着从点 ab 的直线为对象设置动画,但我希望它使用上面的 escapeOutBounce 曲线。这意味着它将沿着从 ab 的精确路线,但会以比当前基于贝塞尔曲线的 CAMediaTimingFunction 更复杂的方式加速和减速。

  2. 让该线成为由 CGPath 指定的任意曲线移动。它仍应沿着该曲线移动,但应以与线条示例中相同的方式加速和减速。

理论上我认为它应该像这样工作:

让我们将运动曲线描述为关键帧动画move(t) = p,其中t是时间[0..1],p em> 是在时间 t 计算的位置。因此,move(0) 返回曲线起点的位置,move(0.5) 返回曲线的中间位置,move(1) 返回曲线末尾的位置。使用计时函数 time(T) = tmove 提供 t 值应该可以满足我的需求。对于弹跳效果,计时函数应为 time(0.8)time(0.8) 返回相同的 t 值(仅作为示例) 。只需更换定时函数即可得到不同的效果。

(是的,可以通过创建和连接四个来回的线段来进行线弹跳,但这不是必需的。毕竟,它只是一个映射时间<的简单线性函数/em> 值到位置。)

我希望我说得有道理。

最佳答案

我发现了这个:

Cocoa with Love - Parametric acceleration curves in Core Animation

但我认为通过使用 block 可以使其变得更简单且更具可读性。因此,我们可以在 CAKeyframeAnimation 上定义一个类别,如下所示:

CAKeyframeAnimation+Parametric.h:

// this should be a function that takes a time value between 
// 0.0 and 1.0 (where 0.0 is the beginning of the animation
// and 1.0 is the end) and returns a scale factor where 0.0
// would produce the starting value and 1.0 would produce the
// ending value
typedef double (^KeyframeParametricBlock)(double);

@interface CAKeyframeAnimation (Parametric)

+ (id)animationWithKeyPath:(NSString *)path
function:(KeyframeParametricBlock)block
fromValue:(double)fromValue
toValue:(double)toValue;

CAKeyframeAnimation+Parametric.m:

@implementation CAKeyframeAnimation (Parametric)

+ (id)animationWithKeyPath:(NSString *)path
function:(KeyframeParametricBlock)block
fromValue:(double)fromValue
toValue:(double)toValue {
// get a keyframe animation to set up
CAKeyframeAnimation *animation =
[CAKeyframeAnimation animationWithKeyPath:path];
// break the time into steps
// (the more steps, the smoother the animation)
NSUInteger steps = 100;
NSMutableArray *values = [NSMutableArray arrayWithCapacity:steps];
double time = 0.0;
double timeStep = 1.0 / (double)(steps - 1);
for(NSUInteger i = 0; i < steps; i++) {
double value = fromValue + (block(time) * (toValue - fromValue));
[values addObject:[NSNumber numberWithDouble:value]];
time += timeStep;
}
// we want linear animation between keyframes, with equal time steps
animation.calculationMode = kCAAnimationLinear;
// set keyframes and we're done
[animation setValues:values];
return(animation);
}

@end

现在用法将如下所示:

// define a parametric function
KeyframeParametricBlock function = ^double(double time) {
return(1.0 - pow((1.0 - time), 2.0));
};

if (layer) {
[CATransaction begin];
[CATransaction
setValue:[NSNumber numberWithFloat:2.5]
forKey:kCATransactionAnimationDuration];

// make an animation
CAAnimation *drop = [CAKeyframeAnimation
animationWithKeyPath:@"position.y"
function:function fromValue:30.0 toValue:450.0];
// use it
[layer addAnimation:drop forKey:@"position"];

[CATransaction commit];
}

我知道这可能不像您想要的那么简单,但这是一个开始。

关于iphone - 如何使用 Core Animation 创建自定义缓动函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5161465/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com