【问题标题】:Progress circle duration is not like expected进度圈持续时间与预期不同
【发布时间】:2023-03-17 18:30:01
【问题描述】:

我希望视图圈进度的持续时间恰好持续 1 秒,但在我的应用中,它只持续大约 0.84 秒。

动图:

在 viewDidLoad 中:

    let shapeLayer = CAShapeLayer()

    let center = view.center
    let trackLayer = CAShapeLayer()
    let circularPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
    trackLayer.path = circularPath.cgPath
    trackLayer.strokeColor = UIColor.lightGray.cgColor
    trackLayer.lineWidth = 10
    trackLayer.fillColor = UIColor.clear.cgColor
    trackLayer.lineCap = kCALineCapRound
    view.layer.addSublayer(trackLayer)
    shapeLayer.path = circularPath.cgPath
    shapeLayer.strokeColor = UIColor.red.cgColor
    shapeLayer.lineWidth = 10
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.lineCap = kCALineCapRound
    shapeLayer.strokeEnd = 0
    view.layer.addSublayer(shapeLayer)
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))

如果你点击屏幕:

@objc private func handleTap() {
    let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
    basicAnimation.toValue = 1

    ///Here is defined the duration
    basicAnimation.duration = 1

    basicAnimation.fillMode = kCAFillModeForwards
    basicAnimation.isRemovedOnCompletion = false

    shapeLayer.add(basicAnimation, forKey: "urSoBasic")
}

我也试过:

basicAnimation.duration = CFTimeInterval(1)

但效果并不好。

【问题讨论】:

    标签: ios swift animation swift4 duration


    【解决方案1】:

    它必须持续 1 秒,它可能在你看到它之前已经运行了 0.15 秒左右。 ViewDidLoad 并不意味着你看到它。尝试将 beginTime 设置为 CACurrentMediaTime() + 2.0 并再次测量。或者在视图中运行它时确实出现了 CACurrentMediaTime() 的 beginTime。

    更新: 使用您的代码

    import UIKit
    
    class ViewController: UIViewController {
    
        var shapeLayer = CAShapeLayer()
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            shapeLayer = CAShapeLayer()
    
            let center = view.center
            let trackLayer = CAShapeLayer()
            let circularPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
            trackLayer.path = circularPath.cgPath
            trackLayer.strokeColor = UIColor.lightGray.cgColor
            trackLayer.lineWidth = 10
            trackLayer.fillColor = UIColor.clear.cgColor
            trackLayer.lineCap = kCALineCapRound
            view.layer.addSublayer(trackLayer)
            shapeLayer.path = circularPath.cgPath
            shapeLayer.strokeColor = UIColor.red.cgColor
            shapeLayer.lineWidth = 10
            shapeLayer.fillColor = UIColor.clear.cgColor
            shapeLayer.lineCap = kCALineCapRound
            shapeLayer.strokeEnd = 0
            view.layer.addSublayer(shapeLayer)
            view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
        }
    
    
        @objc private func handleTap() {
            //prints //the time when the animation start is 30830.886492681
            print("the time when the animation start is \(CACurrentMediaTime())")
            CATransaction.begin()
            let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
            basicAnimation.toValue = 1
            ///Here is defined the duration
            basicAnimation.duration = 1
            basicAnimation.fillMode = kCAFillModeForwards
            basicAnimation.isRemovedOnCompletion = false
            //here i make sure it starts at the current time
            basicAnimation.beginTime = CACurrentMediaTime()
            CATransaction.setCompletionBlock {
                //prints the current Time is 30831.895261542
                print("the current Time is \(CACurrentMediaTime())")
            }
            shapeLayer.add(basicAnimation, forKey: "urSoBasic")
            CATransaction.commit()
        }
    
    
    }
    

    在我的示例中,它持续了多毫秒,尽管我敢打赌,这是动画实际开始时的帧差。请记录你的而不是使用视频,看看它是否持续了它应该持续的时间。如果不是,我们还缺少什么其他代码。您还有其他可能阻塞主线程的东西吗?

    【讨论】:

    • 很抱歉,我不明白您在 CACurrentMediaTime() + 2.0 上对 beginTime 的意思。
    • beginTime 是在CAMediaTiming 协议中声明的属性,您可以为您的basicAnimation 对象设置它,因为它符合协议。建议的值是当前时间 + 2 秒,以便您能够在更清晰的时间开始动画时查看并直观地验证控件(2 秒应该足够了,除非您在显示它之前很久就加载视图)。
    • 正如 A-Live 所说的 animation.beginTime = CACurrentMediaTime() + 0.1。这将起到延迟的作用,尽管它还有其他用途。只要知道 viewDidLoad 并不意味着它在屏幕上,因此该图层可能在您看到它之前就已动画。在 viewDidAppear 中执行此操作更有意义,可能对于您正在执行的操作,只需将 beginTime 设置为 CACurrentMediaTime(),这基本上就像您所看到的屏幕时间 0。
    • 是的,为我认为您正在尝试做的事情移动代码。在 viewdidAppear 中无需延迟,因此只需 CACurrentMediaTime 作为 beginTime。
    • 更新了记录实际时间的代码。如果对您来说有差异,那么可能有我们没有看到的代码。
    猜你喜欢
    • 1970-01-01
    • 2010-12-18
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    相关资源
    最近更新 更多