Swift 3中的动画曲线 [英] Animated curve line in Swift 3

查看:133
本文介绍了Swift 3中的动画曲线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想画一些贝塞尔曲线,并用波浪效果为其设置动画,

I want to draw some bezier lines and I want to animate them with a wave effect,

示例

您对我该怎么做有一些想法?贝塞尔曲线是最好的方法吗? 我为此只找到了2个库,但是它们对我所需的库并不是真正有用,不幸的是,我尝试修改一个库的代码,但没有成功 https://github.com/yourtion/YXWaveView

Do you have some ideas about how I can do this ? Bezier line is it the best method to do it ? I found only 2 libs for this, but they are not really useful for what I need, I try to modify the code of one lib, unfortunately without success https://github.com/yourtion/YXWaveView

我找到了这个库 https://antiguab.github.io/bafluidview/可以完成工作,但是它是用obj-c编写的,也许您很快就知道了类似的内容

I found this lib, https://antiguab.github.io/bafluidview/ which does the work, but it written in obj-c, maybe you know something like this in swift

推荐答案

您可以使用显示链接,这是一种针对屏幕刷新率进行了优化的特殊计时器,用于更改要呈现的path.显示链接的处理程序应计算已过去的时间,并相应地修改要渲染的路径.您可以使用CAShapeLayer呈现路径,也可以使用自定义的UIView子类.形状层可能更容易:

You can use a display link, a special kind of timer optimized for screen refresh rates, to change the path that is being rendered. The handler for the display link should calculate the amount of time that has elapsed and modify the path to be rendered accordingly. You can either use a CAShapeLayer to render the path, or you can use a custom UIView subclass. The shape layer is probably easier:

class ViewController: UIViewController {

    private weak var displayLink: CADisplayLink?
    private var startTime: CFTimeInterval = 0

    /// The `CAShapeLayer` that will contain the animated path

    private let shapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.strokeColor = UIColor.white.cgColor
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.lineWidth = 3
        return shapeLayer
    }()

    // start the display link when the view appears

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        view.layer.addSublayer(shapeLayer)
        startDisplayLink()
    }

    // Stop it when it disappears. Make sure to do this because the
    // display link maintains strong reference to its `target` and
    // we don't want strong reference cycle.

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        stopDisplayLink()
    }

    /// Start the display link

    private func startDisplayLink() {
        startTime = CACurrentMediaTime()
        self.displayLink?.invalidate()
        let displayLink = CADisplayLink(target: self, selector:#selector(handleDisplayLink(_:)))
        displayLink.add(to: .main, forMode: .common)
        self.displayLink = displayLink
    }

    /// Stop the display link

    private func stopDisplayLink() {
        displayLink?.invalidate()
    }

    /// Handle the display link timer.
    ///
    /// - Parameter displayLink: The display link.

    @objc func handleDisplayLink(_ displayLink: CADisplayLink) {
        let elapsed = CACurrentMediaTime() - startTime
        shapeLayer.path = wave(at: elapsed).cgPath
    }

    /// Create the wave at a given elapsed time.
    ///
    /// You should customize this as you see fit.
    ///
    /// - Parameter elapsed: How many seconds have elapsed.
    /// - Returns: The `UIBezierPath` for a particular point of time.

    private func wave(at elapsed: Double) -> UIBezierPath {
        let elapsed = CGFloat(elapsed)
        let centerY = view.bounds.midY
        let amplitude = 50 - abs(elapsed.remainder(dividingBy: 3)) * 40

        func f(_ x: CGFloat) -> CGFloat {
            return sin((x + elapsed) * 4 * .pi) * amplitude + centerY
        }

        let path = UIBezierPath()
        let steps = Int(view.bounds.width / 10)

        path.move(to: CGPoint(x: 0, y: f(0)))
        for step in 1 ... steps {
            let x = CGFloat(step) / CGFloat(steps)
            path.addLine(to: CGPoint(x: x * view.bounds.width, y: f(x)))
        }

        return path
    }
}

唯一棘手的部分是编写一个wave函数,该函数在特定时间产生UIBezierPath,并随着时间的流逝而反复调用时产生期望的效果.在此示例中,我正在绘制一个正弦曲线,其中的振幅和偏移量会根据生成路径时所经过的时间而有所不同,但是您可以在渲染中做任何您想做的事情.希望这可以说明基本思想.

The only tricky part is writing a wave function that yields a UIBezierPath for a particular time and yields the desired effect when you call it repeatedly as time passes. In this one, I'm rendering a sine curve, where the amplitude and the offset vary based upon the time that has elapsed at the point that the path is generated, but you can do whatever you want in your rendition. Hopefully this illustrates the basic idea.

上面的代码产生:

这篇关于Swift 3中的动画曲线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆