CAAnimation 在周期性动画进度间隔中调用方法?

发布于 2024-09-10 05:21:26 字数 1533 浏览 3 评论 0原文

假设我想要制作一个向右滚动 1000 像素的球的动画,并在过程中指定一个计时函数 - 像这样:

UIView *ball = [[UIView alloc] initWithFrame:CGRectMake(0,0,30,30)];
CABasicAnimation* anim =
        [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
anim.toValue = [NSNumber numberWithFloat:ball.frame.origin.x + 1000.0];
                                            // move 1000 pixels to the right
anim.duration = 10.0;
anim.timingFunction = [CAMediaTimingFunction functionWithControlPoints:
                      0.1 :0.0 :0.3 :1.0]; // accelerate fast, decelerate slowly
[ball.layer addAnimation:anim forKey:@"myMoveRightAnim"];

我最终想要的是有一个方法,例如 -(void )animationProgressCallback:(float)progress,在动画过程中以动画进度的固定间隔以开始值和结束值之间的绝对“距离”来调用,即忽略时间功能。

我将尝试用上面的例子来解释,球向右滚动 1000px(用 y 轴绘制,在我们的例子中为 100%=1000px):

alt text

我希望每当球前进 250 像素时就调用我的回调方法。由于计时功能,前 250 个像素可能会在 ti0=2 秒内到达,总距离的一半在 ti1= 0.7 秒后到达(快速加速踢)在)中,750px 标记又过了 ti2= 1.1 秒,并且需要剩余 ti3= 5.2 秒才能到达 100% (1000px) 标记。

什么会很棒,但没有提供:

如果动画按照描述在动画进度间隔中调用委托方法,我就不需要问这个问题......;-)

想法如何解决问题:

我能想到的一种解决方案是计算贝塞尔曲线的值,将其映射到 tik 值(我们知道总动画持续时间),并且当动画开始后,我们按顺序手动执行带有这些延迟的 animationProgresssCallback: 选择器。

显然,这是疯狂的(手动计算贝塞尔曲线?),更重要的是,不可靠(我们不能依赖动画线程和主线程同步——或者我们可以吗?)。

有什么想法吗?

期待您的想法!

Say I want to animate a ball rolling 1000 pixels to the right, specifying a timing function in the process – something like this:

UIView *ball = [[UIView alloc] initWithFrame:CGRectMake(0,0,30,30)];
CABasicAnimation* anim =
        [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
anim.toValue = [NSNumber numberWithFloat:ball.frame.origin.x + 1000.0];
                                            // move 1000 pixels to the right
anim.duration = 10.0;
anim.timingFunction = [CAMediaTimingFunction functionWithControlPoints:
                      0.1 :0.0 :0.3 :1.0]; // accelerate fast, decelerate slowly
[ball.layer addAnimation:anim forKey:@"myMoveRightAnim"];

What I ultimately want is to have a method, say -(void)animationProgressCallback:(float)progress, be called during the animation, in regular intervals of the animation's progress in terms of the absolute "distance" between start and end values, i.e. ignoring the timing function.

I'll try to explain with the above example with the ball rolling 1000px to the right (charted by the y axis, in our case 100%=1000px):

alt text

I want my callback method to be invoked whenever the ball has progressed 250 pixels. Because of the timing function, the first 250 pixels might be reached in ti0=2 seconds, half the total distance reached just ti1= 0.7 seconds later (fast acceleration kicks in), the 750px mark another ti2= 1.1 seconds later, and needing the remaining ti3= 5.2 seconds to reach the 100% (1000px) mark.

What would be great, but isn't provided:

If the animation called a delegate method in animation-progress intervals as described, I wouldn't need to ask this question… ;-)

Ideas how to solve the problem:

One solution I can think of is to calculate the bezier curve's values, map that to the tik values (we know the total animation duration), and when the animation is started, we sequentially perform our animationProgresssCallback: selector with those delays manually.

Obviously, this is insane (calculating bezier curves manually??) and, more importantly, unreliable (we can't rely on the animation thread and the main thread to be in sync – or can we?).

Any ideas??

Looking forward to your ideas!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

断舍离 2024-09-17 05:21:26

解决问题的想法:

我能想到的一个解决方案是
计算贝塞尔曲线的值,
将其映射到 tik 值(我们知道
总动画持续时间),以及
当动画开始时,我们
依次执行我们的
动画进度回调:选择器
手动进行这些延迟。

显然,这是疯狂的(计算
手动贝塞尔曲线?)以及,更多
重要的是,不可靠(我们不能依赖
在动画线程和主线程上
线程同步——我们可以吗?)。

其实这个是靠谱的。 CoreAnimation 是基于时间的,因此您可以使用委托在动画真正开始时收到通知。
关于计算贝塞尔曲线路径......我们这样看:如果你想在 OpenGLES 中实现一个表面,你必须计算三次贝塞尔曲线,情况可能会更糟!哈哈。你的情况只是一维,如果你懂数学的话,这并不难。

Ideas how to solve the problem:

One solution I can think of is to
calculate the bezier curve's values,
map that to the tik values (we know
the total animation duration), and
when the animation is started, we
sequentially perform our
animationProgresssCallback: selector
with those delays manually.

Obviously, this is insane (calculating
bezier curves manually??) and, more
importantly, unreliable (we can't rely
on the animation thread and the main
thread to be in sync – or can we?).

Actually this is reliable. CoreAnimation is time based, so you could use the delegate to be notified when the animation really starts.
And about calculating the bezier path... well look it this way: It could be worse if you would want to implement a surface in OpenGLES you would have to calculate a Cubic Bezier!. lol. Your case is only one dimension, is not that hard if you know the maths.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文