【问题标题】:CAShapeLayer strange animation behaviorCAShapeLayer 奇怪的动画行为
【发布时间】:2017-03-08 10:52:30
【问题描述】:

我正在尝试创建一个动画,其中两条线在用户拖动 UIView 时淡出并在用户释放拖动时淡入。
因此我有两个函数undrawLines(在平移手势开始时调用)和redrawLines(在平移手势结束时调用),它们由我的UIPanGestureRecognizer 动作处理程序调用。

func undrawLines() {

    line1.opacity = 0.0
    line2.opacity = 0.0

    line1.removeAllAnimations()
    line2.removeAllAnimations()

    let opacityLine = CABasicAnimation(keyPath: "opacity")
    opacityLine.fromValue = 1.0
    opacityLine.toValue = 0.0
    opacityLine.duration = 0.15

    line1.add(opacityLine, forKey: "disappearLine1")
    line2.add(opacityLine, forKey: "disappearLine2")

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: {
        mill.line1.removeFromSuperlayer()
        mill.line2.removeFromSuperlayer()
    })
}

func redrawLines() {

    line1.opacity = 1.0
    line2.opacity = 1.0

    print("redraw")
    line1.removeAllAnimations()
    line2.removeAllAnimations()

    self.layer.addSublayer(line1)
    self.layer.addSublayer(line2)

    let opacityLine = CABasicAnimation(keyPath: "opacity")
    opacityLine.fromValue = 0.0
    opacityLine.toValue = 1.0
    opacityLine.duration = 0.15

    line1.add(opacityMill, forKey: "appearLine1")
    line2.add(opacityMill, forKey: "appearLine2")
}

问题是当undrawLines 动画仍在运行时调用redrawLines 时,线条显示出奇怪的行为并且不透明度为0。
这是一个演示,第一部分显示应该如何,第二部分显示错误:

【问题讨论】:

    标签: ios animation core-animation cashapelayer


    【解决方案1】:

    我相信您的问题是您的完成处理程序的竞争条件:

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: {
        mill.line1.removeFromSuperlayer()
        mill.line2.removeFromSuperlayer()
    })
    

    如果您的用户释放,因此 redrawLines 在 0.3 秒超时之前被调用,这仍然会被调用并删除行。

    您可能希望保留一个指示当前意图的状态标志,然后在异步回调中检查它:

    func undrawLines() {
    
        self.linesHidden = true // update state
    
        line1.opacity = 0.0
        line2.opacity = 0.0
    
        line1.removeAllAnimations()
        line2.removeAllAnimations()
    
        let opacityLine = CABasicAnimation(keyPath: "opacity")
        opacityLine.fromValue = 1.0
        opacityLine.toValue = 0.0
        opacityLine.duration = 0.15
    
        line1.add(opacityLine, forKey: "disappearLine1")
        line2.add(opacityLine, forKey: "disappearLine2")
    
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: { [weak self] in
            if self?.linesHidden == true { // check this is still what we want to do
                mill.line1.removeFromSuperlayer()
                mill.line2.removeFromSuperlayer()
            }
        })
    }
    
    func redrawLines() {
    
        self.linesHidden = false // update state
    
        line1.opacity = 1.0
        line2.opacity = 1.0
    
        print("redraw")
        line1.removeAllAnimations()
        line2.removeAllAnimations()
    
        self.layer.addSublayer(line1)
        self.layer.addSublayer(line2)
    
        let opacityLine = CABasicAnimation(keyPath: "opacity")
        opacityLine.fromValue = 0.0
        opacityLine.toValue = 1.0
        opacityLine.duration = 0.15
    
        line1.add(opacityMill, forKey: "appearLine1")
        line2.add(opacityMill, forKey: "appearLine2")
    }
    

    您显然需要将实例 var linesHidden 添加到该类中才能正常工作:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 2019-10-09
      • 2016-08-29
      • 1970-01-01
      • 2016-05-25
      • 2013-02-14
      • 2013-03-17
      相关资源
      最近更新 更多