代码之家  ›  专栏  ›  技术社区  ›  netdigger

使用CAShapeLayer设置遮罩部分透明度的动画

  •  0
  • netdigger  · 技术社区  · 7 年前

    .brown backgroundColor

    backgroundView ,而 backgroundColor: UIColor.black.withAlphaComponent(0.5) .

    然后我想在这个盒子里放一个透明的盒子 背景视图 其中显示了参考底图视图。我已经做到了这一点,但我不能通过设置透明度的动画来实现,我的代码只会将“剪切区域”增长到所需的大小,而不是设置透明度的动画。

    背景视图为棕色,0.5 alpha

    Brown view with the backgroundView and it's 0.5 alpha

    Added layer to backgroundView shows part of the brown view

    我编写的代码是这样的:

    func addIndicatorTo(global frame: CGRect) {
        let shape = CAShapeLayer()
        let targetRect = convert(frame, from: nil).insetBy(dx: -4, dy: -4)
        let animation = CABasicAnimation(keyPath: "path")
    
        let toPath = CGMutablePath()
        toPath.addRect(bounds)
        toPath.addPath(UIBezierPath(roundedRect: targetRect,
                                    byRoundingCorners: .allCorners,
                                    cornerRadii: CGSize(width: 4, height: 4)).cgPath)
        toPath.closeSubpath()
    
        let fromPath = CGMutablePath()
        fromPath.addRect(bounds)
        fromPath.addPath(UIBezierPath(roundedRect: targetRect.insetBy(dx: targetRect.width / 2,
                                                                      dy: targetRect.height / 2),
                                      byRoundingCorners: .allCorners,
                                      cornerRadii: CGSize(width: 4, height: 4)).cgPath)
        fromPath.closeSubpath()
    
        animation.fromValue = fromPath
        animation.toValue = toPath
        animation.duration = 0.5
    
        shape.fillRule = .evenOdd
        shape.path = animation.fromValue as! CGPath
    
        backgroundView.layer.mask = shape
        shape.add(animation, forKey: nil)
    
        CATransaction.begin()
        CATransaction.setDisableActions(true)
        shape.path = toPath
        CATransaction.commit()
    }
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   netdigger    7 年前

    不确定这是否是一个“好”的解决方案。但我会一直坚持下去,直到有人告诉我如何更优雅地解决它!

    boxLayer 在“剪切”区域中绘制。然后,我只需设置动画 opacity boxLayer

    func addIndicatorTo(global frame: CGRect) {
        let maskLayer = CAShapeLayer()
        let boxLayer = CAShapeLayer()
    
        let targetRect = convert(frame, from: nil).insetBy(dx: -4, dy: -4)
        let animation = CABasicAnimation(keyPath: "opacity")
    
        let toPath = CGMutablePath()
    
        let boxPath = UIBezierPath(roundedRect: targetRect,
                                   byRoundingCorners: .allCorners,
                                   cornerRadii: CGSize(width: 4, height: 4)).cgPath
        toPath.addRect(bounds)
        toPath.addPath(boxPath)
        toPath.closeSubpath()
    
        boxLayer.fillColor = UIColor.black.withAlphaComponent(0.5).cgColor
        boxLayer.path = boxPath
    
        animation.fromValue = 1.0
        animation.toValue = 0.0
        animation.duration = 0.5
    
        maskLayer.fillRule = .evenOdd
        maskLayer.path = toPath
    
        backgroundView.layer.mask = maskLayer
        layer.addSublayer(boxLayer)
        boxLayer.add(animation, forKey: nil)
    
        CATransaction.begin()
        CATransaction.setDisableActions(true)
        boxLayer.opacity = 0.0
        CATransaction.commit()
    }