沿贝塞尔路径的一部分为 UIView 设置动画
Animate a UIView along a part of a bezier path
我正在尝试沿着贝塞尔路径的一部分为 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")
但是,这只是将视图移动到所需的点,而不是对其进行动画处理。如何在贝塞尔路径的一部分上为视图设置动画?
谢谢
我前几天做了一个类似的动画:
// 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
设置为零和时间偏移。为什么需要它们?
我建议只使用上面代码中的参数尝试动画,然后尝试从中调整它。
您可以通过修改 "complete" 动画的时间和包装它的动画组来完成此操作。
为了说明这种动画的计时如何工作,想象一下——而不是为路径上的位置设置动画——正在为一种颜色设置动画。然后,从一种颜色到另一种颜色的完整动画可以这样表示,其中更右边的值是稍后的值——所以最左边是开始值,最右边是结束值:
注意这个动画的"timing"是线性的。这是故意的,因为最终结果的 "timing" 将在稍后配置。
在这个动画中,想象一下我们只想为中间的三分之一设置动画,即动画的这一部分:
只对这部分动画进行动画处理需要几个步骤。
首先,将 "complete" 动画配置为具有线性时间(或者在动画沿路径的情况下;具有 节奏 计算模式)并持续时间为 "complete"。
例如:如果您希望为动画的三分之一设置动画并且 需要 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
这意味着当前动画是这样说明的(完整动画):
接下来,为了让动画 "starts" 进入完整动画的三分之一,我们 "offset" 它的时间是持续时间的三分之一:
animation.timeOffset = relativeStart * innerDuration
现在动画是这样说明的,从它的结束值到它的开始值偏移和环绕:
接下来,为了只显示此动画的一部分,我们创建了一个具有所需持续时间的动画组,并仅向其中添加 "complete" 动画。
let group = CAAnimationGroup()
group.animations = [animation]
group.duration = duration
即使该组包含一个 3 秒长的动画,它也会在 1 秒后结束,这意味着永远不会显示偏移量 "complete" 动画的 2 秒。
现在群动画是这样的,在"complete"动画的三分之一处结束:
如果仔细观察,您会发现这(未淡出的部分)是 "complete" 动画的中间三分之一。
现在这个组在想要的值之间进行动画处理,它(组)可以进一步配置然后添加到图层。例如,如果您希望此 "partial" 动画反转、重复并具有时间曲线,您可以在组上配置这些内容:
group.repeatCount = HUGE
group.autoreverses = true
group.timingFunction = CAMediaTimingFunction(name: "easeInEaseOut")
有了这个额外的配置,动画组将如下所示:
作为一个更具体的示例,这是我使用此技术创建的动画(实际上所有代码都来自该示例),它像钟摆一样来回移动图层。在这种情况下,"complete" 动画是一个 "position" 沿着完整圆圈路径的动画
我正在尝试沿着贝塞尔路径的一部分为 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")
但是,这只是将视图移动到所需的点,而不是对其进行动画处理。如何在贝塞尔路径的一部分上为视图设置动画?
谢谢
我前几天做了一个类似的动画:
// 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
设置为零和时间偏移。为什么需要它们?
我建议只使用上面代码中的参数尝试动画,然后尝试从中调整它。
您可以通过修改 "complete" 动画的时间和包装它的动画组来完成此操作。
为了说明这种动画的计时如何工作,想象一下——而不是为路径上的位置设置动画——正在为一种颜色设置动画。然后,从一种颜色到另一种颜色的完整动画可以这样表示,其中更右边的值是稍后的值——所以最左边是开始值,最右边是结束值:
注意这个动画的"timing"是线性的。这是故意的,因为最终结果的 "timing" 将在稍后配置。
在这个动画中,想象一下我们只想为中间的三分之一设置动画,即动画的这一部分:
只对这部分动画进行动画处理需要几个步骤。
首先,将 "complete" 动画配置为具有线性时间(或者在动画沿路径的情况下;具有 节奏 计算模式)并持续时间为 "complete"。
例如:如果您希望为动画的三分之一设置动画并且 需要 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
这意味着当前动画是这样说明的(完整动画):
接下来,为了让动画 "starts" 进入完整动画的三分之一,我们 "offset" 它的时间是持续时间的三分之一:
animation.timeOffset = relativeStart * innerDuration
现在动画是这样说明的,从它的结束值到它的开始值偏移和环绕:
接下来,为了只显示此动画的一部分,我们创建了一个具有所需持续时间的动画组,并仅向其中添加 "complete" 动画。
let group = CAAnimationGroup()
group.animations = [animation]
group.duration = duration
即使该组包含一个 3 秒长的动画,它也会在 1 秒后结束,这意味着永远不会显示偏移量 "complete" 动画的 2 秒。
现在群动画是这样的,在"complete"动画的三分之一处结束:
如果仔细观察,您会发现这(未淡出的部分)是 "complete" 动画的中间三分之一。
现在这个组在想要的值之间进行动画处理,它(组)可以进一步配置然后添加到图层。例如,如果您希望此 "partial" 动画反转、重复并具有时间曲线,您可以在组上配置这些内容:
group.repeatCount = HUGE
group.autoreverses = true
group.timingFunction = CAMediaTimingFunction(name: "easeInEaseOut")
有了这个额外的配置,动画组将如下所示:
作为一个更具体的示例,这是我使用此技术创建的动画(实际上所有代码都来自该示例),它像钟摆一样来回移动图层。在这种情况下,"complete" 动画是一个 "position" 沿着完整圆圈路径的动画