【问题标题】:Animate a UIView along a part of a bezier path沿贝塞尔路径的一部分为 UIView 设置动画
【发布时间】:2018-06-23 11:24:26
【问题描述】:

我正在尝试沿贝塞尔路径的一部分为 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")

但是,这只是将视图移动到所需的点而不是动画。您如何在贝塞尔路径的一部分上为视图设置动画?

谢谢

【问题讨论】:

标签: ios swift animation uiview core-animation


【解决方案1】:

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

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

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

在这个动画中,假设我们只希望动画中间三分之一,即动画的这一部分:

只需几个步骤即可仅对动画的这一部分进行动画处理。

首先,将“完整”动画配置为具有线性时序(或者在动画沿路径的情况下;具有节奏计算模式)并具有“完整”持续时间.

例如:如果您要为三分之一的动画制作动画,并且 需要 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")

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


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

【讨论】:

    【解决方案2】:

    几天前我做了一个类似的动画:

    // 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 设置为零和一个时间偏移量。你为什么需要它们? 我建议仅使用上述代码中的参数尝试动画,然后尝试根据它们进行调整。

    【讨论】:

    • 这使得视图沿着整个贝塞尔路径动画,而不是它的一部分。它与这里描述的非常相似:stackoverflow.com/questions/34286904/…
    • 抱歉,没有正确阅读您的问题。恐怕没有办法只为路径的一部分设置动画。我能想到的唯一解决方案是为您感兴趣的部分创建另一个与原始路径重叠的路径
    猜你喜欢
    • 1970-01-01
    • 2012-11-16
    • 2015-05-01
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多