获取在视图层上完成的动画百分比

时间:2018-04-19 08:00:53

标签: ios swift calayer

我在视图的layer上以progress bar的形式制作动画。我可以暂停和恢复图层动画,但无法在暂停时获得完成动画的百分比。

动画代码视图宽度

 UIView.animate(withDuration: 3, delay: 0, options: .curveLinear, animations: {
        self.progressView.frame.size.width = self.view.bounds.width - 40
 }, completion: nil)

暂停动画

func pauseLayer(layer: CALayer) {
    let pausedTime: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil)
    layer.speed = 0.0
    layer.timeOffset = pausedTime
}

要恢复的动画代码

func resumeLayer(layer: CALayer) {
    let pausedTime: CFTimeInterval = layer.timeOffset
    layer.speed = 1.0
    layer.timeOffset = 0.0
    layer.beginTime = 0.0
    let timeSincePause: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime

    layer.beginTime = timeSincePause
}

2 个答案:

答案 0 :(得分:1)

诀窍是检查正在设置动画的图层的 presentationLayer 。这是您正在看到的动画模型,以及为什么在评论中您声明宽度从未改变过。这是因为只要添加动画,模型图层值和框架就会更新,您所看到的只是类似电影的presentationLayer。我需要知道你应用的动画类型的原因是我知道我试图获得的表示层的属性。否则你们都会在关于检查bounds.width的评论中走在正确的轨道上来弄清楚动画的进展。给这一点。

import UIKit

class ViewController: UIViewController {

    var fakeProgress = UIView()
    var progressLabel = UILabel()
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let progressContainer = UIView(frame:  CGRect(x: 20, y:50, width: self.view.bounds.width - 40, height: 40))
        progressContainer.backgroundColor = UIColor.lightGray
        fakeProgress = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 40))
        fakeProgress.backgroundColor = .green
        self.view.addSubview(progressContainer)
        progressContainer.addSubview(fakeProgress)

        progressLabel.frame = CGRect(x: 0, y: 0, width: 10, height: 40)
        progressLabel.translatesAutoresizingMaskIntoConstraints = false
        progressContainer.addSubview(progressLabel)
        progressLabel.text = "0%"
        progressLabel.leadingAnchor.constraint(equalTo: progressContainer.leadingAnchor, constant: 4).isActive = true
        progressLabel.centerYAnchor.constraint(equalTo: progressContainer.centerYAnchor, constant: 0).isActive = true


        let button = UIButton(frame: CGRect(x: 20, y: self.view.bounds.height - 60, width: self.view.bounds.width - 40, height: 40))
        button.addTarget(self, action: #selector(toggleAnimation), for: .touchUpInside)
        button.setTitle("press for something", for: .normal)
        button.backgroundColor = UIColor.green
        button.setTitleColor(UIColor.white, for: .normal)
        self.view.addSubview(button)


        UIView.animate(withDuration: 3, delay: 0, options: .curveLinear, animations: {
            self.fakeProgress.frame.size.width = progressContainer.bounds.width
        }, completion: { (finished) in
            self.progressLabel.text = "\(100.0)%"
            self.progressLabel.isHidden = false
        })

        pauseLayer(layer: fakeProgress.layer)
    }

    @objc func toggleAnimation(){

        if let presentation = fakeProgress.layer.presentation(){
            let width = presentation.bounds.width
            let progress = (width/(self.view.bounds.width - 40)) * 100
            print("the progress is \(progress)")
            progressLabel.text = "\((ceil(progress * 100))/100)%"
        }else{
             let progress = (fakeProgress.frame.width/(self.view.bounds.width - 40)) * 100
            if progress == 100{
                print("finished")
                progressLabel.text = "\(100)%"
            }else{
                print("not started")
                progressLabel.text = "\(0)%"
            }
        }

        if fakeProgress.layer.speed == 0{
            resumeLayer(layer: fakeProgress.layer)
        }else{
            pauseLayer(layer: fakeProgress.layer)
        }

    }


    func pauseLayer(layer: CALayer) {
        progressLabel.isHidden = false
        let pausedTime: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil)
        layer.speed = 0.0
        layer.timeOffset = pausedTime
    }

    func resumeLayer(layer: CALayer) {
        progressLabel.isHidden = true
        let pausedTime: CFTimeInterval = layer.timeOffset
        layer.speed = 1.0
        layer.timeOffset = 0.0
        layer.beginTime = 0.0
        let timeSincePause: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime

        layer.beginTime = timeSincePause
    }

}

答案 1 :(得分:0)

嗯,它可以手动完成,使用下面的代码来获取动画的开始时间,当动画停止调用函数时,你可以在几秒钟内获得时间,然后你可以在下面的代码中划分时间变量然后动画的总时间乘以100得到你的百分比:)

  var startTime: Double = 0
  var time: Double = 0

  /* 
  When the animation starts, record the time and start a timer using the code below
  */
  startTime = Date().timeIntervalSinceReferenceDate

  //When the animation stops, invalidate the timer and do your percentage equation i described above:


  func timeDifference(timer: Timer) {

    //Total time in seconds
    time = Date().timeIntervalSinceReferenceDate - startTime

    //The rest of your code goes here

  }

否则你可以创建一个具有所需宽度的变量和另一个保持原始宽度的变量,当你停止动画时,等式将是:

fabs(current width - original width) * 100 /desired width
相关问题