【问题标题】:How can I create an iOS CAAnimation and define every interpolated value myself?如何创建 iOS CAAnimation 并自己定义每个插值?
【发布时间】:2019-01-10 21:59:40
【问题描述】:

我想为CAShapeLayer 的路径设置动画。但是,此路径是使用许多弧创建的。路径的开始值和结束值中的弧数相同。但是,由于弧的长度不同,这似乎意味着实际路径使用不同数量的贝塞尔控制点。这意味着动画是不可预测的并且非常有问题*。

到目前为止,我的解决方案是创建一个CAKeyFrameAnimation,并放入大量关键帧。它仅适用于每秒非常多的关键帧。 (大约 200 到 300)。任何降低,故障*开始出现。

这种方法非常粗糙,因为它的成功取决于实际设备上的实际帧速率,并且创建的关键帧实例比动画实际需要的多,浪费内存。 所以我的问题是:有没有办法创建一个我必须以某种方式创造每一个价值的动画?我正在想象一些基于委托的方法,在这种方法中,我被问到一个基于关键时间的值。我不知道解决我的问题的最佳方法是什么。

*注意:我所说的故障是只出现一帧的奇怪路径。

【问题讨论】:

    标签: ios swift animation caanimation


    【解决方案1】:

    您应该尝试使用CADisplayLink

    这是一个例子:

    func setupAnimation() {
        let dispLink = CADisplayLink(target: self, selector: #selector(updateAnimation))
        dispLink.preferredFramesPerSecond = 60 //will update 60 times per second (the default for iOS devices) ... this line of code is optional depending on the fps you want for your animation
        dispLink.add(to: RunLoop.current, forMode: RunLoop.Mode.common)
    }
    
    func updateAnimation() {
        //do your animation code here
    }
    

    使用显示链接会将您的动画链接到屏幕的刷新率,这样它就很流畅了,您基本上可以做任何您想做的事情而不会看起来不连贯

    【讨论】:

      【解决方案2】:

      UIBezierPath,它是基础核心基础类CGPath,在根据弧的角度创建弧时确实使用可变数量的控制点。

      因此,正如您所发现的,如果您尝试为包含不同角度圆弧的路径设置动画,随着路径中控制点数量的变化,您会得到非常奇怪的绘图伪影。

      我建议使用 Catmull-Rom 样条来创建你的弧线。 Catmull-Rom 样条曲线是一种不同类型的三次曲线,其中所有控制点都在曲线上。我从 Erica Sadun 的杰出 iOS Developers' Cookbook 系列中了解了 Catmull-Rom 样条(强烈推荐阅读。)

      如果您创建一个 Catmull-Rom 样条曲线,其中大约 10 个点均匀分布在一个圆周围,您得到的曲线将非常接近一个圆。 (我最初推荐了 8 个控制点,但我只是尝试了一下,描述一个完整圆的曲线在至少有 10 个控制点之前看起来并不完美。)如果你想生成一个包含圆弧的 CGPath较小的角度,生成 10 个控制点,覆盖更少或更多的弧。

      我在 Github 上有一个名为 TrochoidDemo 的项目,它使用 Catmull Rom Splines 创建逼真的水波。您可以忽略其中的大部分内容,但它包含一个文件 SmoothCGPointsArray.swift,它将获取一个控制点数组并使用 Catmull-Rom 样条线返回一个新数组,其中包含描述控制点之间平滑曲线的中间点。

      你想要在那个文件中的函数是smoothPointsInArray(_:granularity:adjustGranularity:)

      adjustGranularity 参数默认为 true。该参数告诉函数根据控制点之间的距离来改变它创建的平滑点的数量。您将需要覆盖默认值并使用adjustGranularity=false 调用该函数,因为对于动画,您总是需要相同数量的点。

      您只需使用一组控制点调用该函数,其中包括您要绘制的每条弧线的 10 个点,无论角度如何。它将返回一个 CGPoints 数组,然后您将使用生成的 GCPoints 数组使用 lineTo() 命令生成 UIBezierPath,然后将 CGPath 从您的 UIBezierPath 提供给您的动画。

      在您的源点数组中,如果您希望给定点成为尖角,请将该点连续添加两次。如果您想要一条线段,请将线段的两个端点添加两次。

      这是一个 8 点近似圆的样子:

      这是一个 10 点近似圆的样子:

      (在上面的每个图像中,Catmull-Rom 近似值以黑色绘制,控制点以蓝色显示,其中 Cocoa 绘制的圆圈以蓝色绘制。注意 Cocoa 使用贝塞尔曲线来创建它的圆圈,所以 Cocoa圆圈也是近似值。)

      【讨论】:

        猜你喜欢
        • 2012-09-02
        • 1970-01-01
        • 1970-01-01
        • 2022-09-23
        • 2010-09-18
        • 1970-01-01
        • 1970-01-01
        • 2019-05-21
        • 2012-09-27
        相关资源
        最近更新 更多