如何计算缓出动画的持续时间以达到所需的初始速度?

时间:2018-01-19 19:04:25

标签: ios animation calayer caanimation

上下文:

我有一个图形,我在后台操作发生时连续旋转:

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = @(M_PI * 2.0);
rotationAnimation.duration = 2;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = HUGE_VALF;

[myImgView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];

在某些时候,这个背景动画结束了,我停止了动画:

[myImgView.layer removeAllAnimations];

但是,当我这样做时,旋转会停在任何地方并且快速回到零旋转。我可以通过将演示值提升到模型值来停止它:

CATransform3D stoppedTransform = myImgView.layer.presentationLayer.transform;
[myImgView.layer removeAllAnimations];
myImgView.layer.transform = stoppedTransform;

这很好用。但理想情况下,我希望继续旋转当前电路的其余部分,并在接近零位旋转时减速并平稳停止。停止动画,将演示文稿提升为模型,并创建一个缓动曲线为零的新动画。像这样:

CATransform3D stoppedTransform = myImgView.layer.presentationLayer.transform;
[myImgView.layer removeAllAnimations];
myImgView.layer.transform = stoppedTransform;
CGFloat currRotation = [[myImgView.layer valueForKeyPath:@"transform.rotation.z"] floatValue];
CABasicAnimation *finishAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
finishAnimation.fromValue = @(currRotation);
finishAnimation.toValue = @(0);
finishAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
finishAnimation.duration = 2; //this is what I need to calculate correctly
[myImgView.layer setValue:@(0) forKeyPath:@"transform.rotation.z"];
[myImgView.layer addAnimation:finishAnimation forKey:@"transform.rotation.z"];

我的问题:

如何使用缓出曲线计算完成动画的持续时间,使其初始速度与现有旋转的速度(当前为每秒π弧度)相匹配,因此没有可见的打嗝?还是有另一种方法可以达到预期的效果吗?

我尝试过使用CASpringAnimation并使用其initialVelocity属性,但它似乎将弹簧拉动质量所赋予的速度与mass一致, stiffnessdamping及其单位不清楚。我可以通过计算持续时间来计算缓出持续时间,就好像它是线性的并将它撞到20%或30%左右。

旁注:由于图层如何报告当前的轮值,因此此处有一些小的复杂性,为了简化问题而移除toValue finishAnimation周围的问题。如果它超过pi弧度(180度),则报告为负值。所以它是这样的:

CGFloat rotationRadians = currRotation / M_PI;
if (rotationRadians < 0)
{
    finishAnimation.duration = (-1 * rotationRadians); //negative means more than halfway through, or more than pi radians.
    finishAnimation.toValue = @(0);
}
else
{
    finishAnimation.duration = (2 - rotationRadians); //positive means less than halfway through, or less than pi radians
    finishAnimation.toValue = @(M_PI * 2);
}

0 个答案:

没有答案