沿着贝塞尔曲线的一部分为UIView制作动画

我正在尝试沿着Bezier路径的一部分动画UIView。 我发现了一种使用此代码将视图移动到路径的任何部分的方法:

let animation = CAKeyframeAnimation(keyPath: "position") animation.path = trackPath.cgPath animation.rotationMode = kCAAnimationRotateAuto animation.speed = 0 animation.timeOffset = offset animation.duration = 1 animation.calculationMode = kCAAnimationPaced square.layer.add(animation, forKey: "animate position along path") 

但是,这只是将视图移动到所需的点,并且不会为其设置动画。 如何在Bezier路径的一部分上为视图设置动画?

谢谢

您可以通过修改“完整”动画的时间和包装它的动画组来完成此操作。

为了说明这种动画的时间是如何工作的,想象 – 而不是沿着路径动画一个位置 – 一个颜色被动画化。 然后,从一种颜色到另一种颜色的完整动画可以这样说明,其中右边的值是稍后的时间 – 所以最左边是起始值,最右边是结束值:

完整的动画

请注意,此动画的“时间”是线性的。 这是故意的,因为最终结果的“时间”将在稍后配置。

在这个动画中,想象一下我们只想动画中间三分之一,动画的这一部分:

动画的一部分

只有几个步骤可以动画动画的这一部分。

首先,将“完整”动画配置为具有线性定时(或者沿着路径动画;具有节奏计算模式)并具有“完整”持续时间。

例如:如果您要为动画的三分之一设置动画需要1秒钟,请将完整动画配置为3秒。

 let relativeStart = 1.0/3.0 let relativeEnd = 2.0/3.0 let duration = 1.0 let innerDuration = duration / (relativeEnd - relativeStart) // 3 seconds // configure the "complete" animation animation.duration = innerDuration 

这意味着当前动画就像这样(完整动画):

完整的动画

接下来,为了让动画“开始”进入完整动画的三分之一,我们将其时间“偏移”持续时间的三分之一:

 animation.timeOffset = relativeStart * innerDuration 

现在,动画如下所示,从其结束值到其起始值进行偏移和包装:

具有时间偏移的动画

接下来,为了使我们只显示此动画的一部分,我们创建一个具有所需持续时间的动画组,并仅向其添加“完整”动画。

 let group = CAAnimationGroup() group.animations = [animation] group.duration = duration 

即使该组包含3秒长的动画,它也会在1秒后结束,这意味着永远不会显示偏移“完成”动画的2秒。

现在,组动画就像这样说明,在“完整”动画的三分之一后结束:

群动画

如果你仔细观察,你会发现这个(没有淡出的部分)是“完整”动画的中间三分之一。

既然该组在所需值之间设置了动画,则可以进一步配置它(组),然后将其添加到图层。 例如,如果您希望此“部分”动画反转,重复并具有时序曲线,您可以在组上配置这些内容:

 group.repeatCount = HUGE group.autoreverses = true group.timingFunction = CAMediaTimingFunction(name: "easeInEaseOut") 

使用此附加配置,动画组将如下所示:

部分动画,自动倒车和重复


作为一个更具体的例子,这是我使用这种技术创建的动画(实际上所有代码都来自该示例),它像钟摆一样来回移动图层。 在这种情况下,“完整”动画是沿着完整圆的路径的“位置”动画

像钟摆一样来回移动的层

几天前我做过类似的动画:

 // I want the animation to go along the circular path of the oval shape let flightAnimation = CAKeyframeAnimation(keyPath: "position") flightAnimation.path = ovalShapeLayer.path // I set this one to make the animation go smoothly along the path flightAnimation.calculationMode = kCAAnimationPaced flightAnimation.duration = 1.5 flightAnimation.rotationMode = kCAAnimationRotateAuto airplaneLayer.add(flightAnimation, forKey: nil) 

我看到你将speed设置为零和时间偏移。 你为什么需要它们? 我建议只使用上面代码中的参数来尝试动画,然后尝试从它们中调整它。