【问题标题】:Animated curve line in Swift 3Swift 3 中的动画曲线
【发布时间】:2017-05-16 16:32:27
【问题描述】:

我想画一些贝塞尔线,我想用波浪效果为它们制作动画,

示例

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

我找到了这个库,https://antiguab.github.io/bafluidview/,它可以完成这项工作,但它是用 obj-c 编写的,也许你在 swift 中知道类似的东西


【问题讨论】:

    标签: swift swift3 uiviewanimation uibezierpath curve


    【解决方案1】:

    您可以使用display link(一种针对屏幕刷新率优化的特殊计时器)来更改正在呈现的path。显示链接的处理程序应该计算已经过去的时间量并相应地修改要呈现的路径。您可以使用CAShapeLayer 来呈现路径,也可以使用自定义UIView 子类。形状层可能更容易:

    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,并在您随着时间的推移重复调用它时产生所需的效果。在这一个中,我正在渲染一条正弦曲线,其中幅度和偏移量会根据路径生成点所经过的时间而变化,但您可以在演绎中做任何您想做的事情。希望这能说明基本思想。

    以上代码产生:

    【讨论】:

    • 嘿。好东西。我想知道哪个是控制波速的变量?
    • 当然,在wave(at:) 中尝试将elapsed 乘以和除以值,这将影响它改变的速度和方式。
    猜你喜欢
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多