【问题标题】:How animate layer.mask changes动画 layer.mask 如何变化
【发布时间】:2019-07-15 22:14:29
【问题描述】:

我在我的应用程序中创建了这个自定义视图,用户可以通过拖动来扩展它,并包含案例的所有动画。为了清楚起见,我想重现几乎相同的 IOS 控制中心动画。到目前为止,我设法获得了几乎所有内容,从手指拖动视图时的扩展动画到使角变圆的可能性。

现在,事实是,除了可以拖动视图之外,我还想在用户在展开之间松开手指时实现动画,以使视图恢复到原来的高度或完成扩张。为此,我使用了用户停止拖动时视图的位置。

当我尝试为UIView.layer.mask 设置动画时,问题就开始了。通过网上的一些研究,我发现了CABasicAnimation 类,并在一个函数中实现了它:

func animateExpandableView(withDuration duration: Double) {

    CATransaction.begin()
    CATransaction.setAnimationDuration(duration)
    CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .easeInEaseOut))

    let maskAnimation = CABasicAnimation(keyPath: "mask")
    maskAnimation.fromValue = profileView.layer.mask

    let bounds = profileView.frame
    let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 8.0, height: 8.0))
    let maskLayer = CAShapeLayer()
    maskLayer.frame = bounds
    maskLayer.path = maskPath.cgPath

    maskAnimation.toValue = maskLayer
    maskAnimation.duration = duration

    profileView.layer.mask = maskLayer
    profileView.layer.add(maskAnimation, forKey: "mask")

    CATransaction.commit()


}

顺便说一句,这不起作用,并且面具的变化没有动画。 我在执行中哪里出错了?

有人建议我从另一个问题中检查此链接;我没有发现它很有用,因为尽管它不适用于我的情况,但答案是用 C 而不是 Swift 编写的。

Animating a CALayer's mask size change

【问题讨论】:

  • 为什么要过滤约束列表?为什么不在创建属性时简单地在属性中存储对约束的引用?使用UIViewPropertyAnimator 您可能会发现这更容易
  • @Paulw11 我还是个菜鸟,我会听从你的建议 :)...什么是 UiPropertyViewAnimator,为什么我不应该使用 Uiview.animate?谢谢
  • 好的,谢谢,我会检查
  • 再问一个问题...如何创建对约束的引用?

标签: ios swift animation uiview mask


【解决方案1】:

我找到了一种解决方法,即无法通过使用计时器重新创建动画来为 mask 属性设置动画。基本上,我将animationDuration 除以 100 并将结果设置为计时器的间隔。然后我将finalHeightinitalHeight 之间的差异除以100 并将其分配给animationStep。完成所有这些设置后,我只需运行计时器 100 个周期,并在每个周期中将 animationStep 添加到 maskHeight 属性。这是我班级的所有代码:

class ExpandableView: UIView {
    //Timer to animate view's mask
    private var animationTimer: Timer? = nil

    //the height of each step for the mask's animation
    private var animationStep: CGFloat? = nil
    private var currentStep: Double = 0

    //Variable responsable to return and set self.mask height.
    private var maskCornerRadii: CGSize? = nil
    private var maskRoundingCorners: UIRectCorner? = nil

    //Variable responsable to return and set self.mask height. it's nil if there isn't any mask
    private var maskHeight: CGFloat? {
        get {return self.layer.mask?.bounds.height}
        set {
            if newValue != nil && maskRoundingCorners != nil && maskCornerRadii != nil {
                let frame = self.bounds
                let bounds = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.width, height: newValue!)
                let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: maskRoundingCorners!, cornerRadii: maskCornerRadii!)
                let maskLayer = CAShapeLayer()
                maskLayer.frame = bounds
                maskLayer.path = maskPath.cgPath

                self.layer.mask = maskLayer
            }
        }
    }


    //Animation function
    func animateMask(from initialHeight: CGFloat, to finalHeight: CGFloat, withDuration duration: Double) {
        let timerInterval = duration * 0.01
        animationStep = (finalHeight - initialHeight) * 0.01
        animationTimer = Timer.scheduledTimer(withTimeInterval: timerInterval, repeats: true, block: { (timer) in

            if self.currentStep <= 100 {
                guard self.animationStep != nil else {
                    fatalError("animationStep is nil")
                }

                guard self.maskHeight != nil else {
                    fatalError("Mask is nil")
                }

                self.maskHeight! += self.animationStep!
                self.currentStep += 1

            } else {
                self.animationTimer!.invalidate()
                self.currentStep = 0
            }
        })
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 2017-05-19
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多