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

如何将多个掩码应用于uiview

  •  1
  • Thomas  · 技术社区  · 7 年前

    我有一个关于如何将多个掩码应用到已经有一个掩码的uiview的问题。

    情况:
    我有一个带有活动遮罩的视图,它在左上角创建了一个洞,这是一个模板uiview,在项目中的任何地方都可以重用。稍后在项目中,我希望能够创建第二个洞,但这次在右下角,这不需要创建一个全新的uiview。

    问题:
    当我应用底部的面具,它当然取代了第一个,从而消除了顶部的孔…有办法把两者结合起来吗?那就把现有的面具和新的结合起来?

    提前谢谢你!

    2 回复  |  直到 7 年前
        1
  •  4
  •   Thomas    7 年前

    基于@sharad的回答,我意识到重新添加视图的rect将使我能够将原来的和新的掩码合并为一个。

    以下是我的解决方案:

    func cutCircle(inView view: UIView, withRect rect: CGRect) {
    
        // Create new path and mask
        let newMask = CAShapeLayer()
        let newPath = UIBezierPath(ovalIn: rect)
    
        // Create path to clip
        let newClipPath = UIBezierPath(rect: view.bounds)
        newClipPath.append(newPath)
    
        // If view already has a mask
        if let originalMask = view.layer.mask,
            let originalShape = originalMask as? CAShapeLayer,
            let originalPath = originalShape.path {
    
            // Create bezierpath from original mask's path
            let originalBezierPath = UIBezierPath(cgPath: originalPath)
    
            // Append view's bounds to "reset" the mask path before we re-apply the original
            newClipPath.append(UIBezierPath(rect: view.bounds))
    
            // Combine new and original paths
            newClipPath.append(originalBezierPath)
    
        }
    
        // Apply new mask
        newMask.path = newClipPath.cgPath
        newMask.fillRule = kCAFillRuleEvenOdd
        view.layer.mask = newMask
    }
    
        2
  •  2
  •   Sharad Chauhan Muhammad Bilal Hussain    7 年前

    这是我在项目中用于在uiview中创建一个圆和一个矩形掩码的代码,您可以替换 UIBezierPath 具有相同弧代码的行:

    func createCircleMask(view: UIView, x: CGFloat, y: CGFloat, radius: CGFloat, downloadRect: CGRect){
        self.layer.sublayers?.forEach { ($0 as? CAShapeLayer)?.removeFromSuperlayer() }
    
        let mutablePath      = CGMutablePath()
        mutablePath.addArc(center: CGPoint(x: x, y: y + radius), radius: radius, startAngle: 0.0, endAngle: 2 * 3.14, clockwise: false)
        mutablePath.addRect(view.bounds)
        let path             = UIBezierPath(roundedRect: downloadRect, byRoundingCorners: [.topLeft, .bottomRight], cornerRadii: CGSize(width: 5, height: 5))
        mutablePath.addPath(path.cgPath)
    
        let mask             = CAShapeLayer()
        mask.path            = mutablePath
        mask.fillRule        = kCAFillRuleEvenOdd
        mask.backgroundColor = UIColor.clear.cgColor
    
    
        view.layer.mask      = mask
    }
    

    传递相同的uiview,它将删除以前的层并在同一uiview上应用新的掩码。

    在这里 mask.fillRule = kCAFillRuleEvenOdd 很重要。如果你注意到有三个 mutablePath.addPath() 功能,什么 kCAFillRuleEvenOdd 是的,它首先创建一个带有圆弧的孔,然后添加该视图边界的矩形,然后添加另一个遮罩以创建第二个孔。