在drawRect中使用iOS反转掩码

时间:2013-01-19 06:23:35

标签: ios uiview core-graphics drawrect masking

使用下面的代码,我成功地屏蔽了我绘图的一部分,但它与我想要屏蔽的相反。这掩盖了绘图的内部,我想掩盖外部。有没有一种简单的方法来反转这个面具?

下面的

myPathUIBezierPath

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGMutablePathRef maskPath = CGPathCreateMutable();
CGPathAddPath(maskPath, nil, myPath.CGPath);
[maskLayer setPath:maskPath];
CGPathRelease(maskPath);
self.layer.mask = maskLayer;

7 个答案:

答案 0 :(得分:36)

即使在形状图层(maskLayer.fillRule = kCAFillRuleEvenOdd;)上填充奇数,您也可以添加一个覆盖整个框架的大矩形,然后添加要遮盖的形状。这实际上会反转掩模。

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGMutablePathRef maskPath = CGPathCreateMutable();
CGPathAddRect(maskPath, NULL, someBigRectangle); // this line is new
CGPathAddPath(maskPath, nil, myPath.CGPath);
[maskLayer setPath:maskPath];
maskLayer.fillRule = kCAFillRuleEvenOdd;         // this line is new
CGPathRelease(maskPath);
self.layer.mask = maskLayer;

答案 1 :(得分:15)

对于Swift 3.0

func mask(viewToMask: UIView, maskRect: CGRect, invert: Bool = false) {
    let maskLayer = CAShapeLayer()
    let path = CGMutablePath()
    if (invert) {
        path.addRect(viewToMask.bounds)
    }
    path.addRect(maskRect)

    maskLayer.path = path
    if (invert) {
        maskLayer.fillRule = kCAFillRuleEvenOdd
    }

    // Set the mask of the view.
    viewToMask.layer.mask = maskLayer;
}

答案 2 :(得分:7)

根据接受的答案,这是Swift中的另一个混搭。我把它变成了一个函数并使invert可选

class func mask(viewToMask: UIView, maskRect: CGRect, invert: Bool = false) {
    let maskLayer = CAShapeLayer()
    let path = CGPathCreateMutable()
    if (invert) {
        CGPathAddRect(path, nil, viewToMask.bounds)
    }
    CGPathAddRect(path, nil, maskRect)

    maskLayer.path = path
    if (invert) {
        maskLayer.fillRule = kCAFillRuleEvenOdd
    }

    // Set the mask of the view.
    viewToMask.layer.mask = maskLayer;
}

答案 3 :(得分:2)

对于Swift 4.2

func mask(viewToMask: UIView, maskRect: CGRect, invert: Bool = false) {
    let maskLayer = CAShapeLayer()
    let path = CGMutablePath()
    if (invert) {
        path.addRect(viewToMask.bounds)
    }
    path.addRect(maskRect)

    maskLayer.path = path
    if (invert) {
        maskLayer.fillRule = .evenOdd
    }

    // Set the mask of the view.
    viewToMask.layer.mask = maskLayer;
}

答案 4 :(得分:1)

快速5

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let red = UIView(frame: view.bounds)
        view.addSubview(red)
        view.backgroundColor = UIColor.cyan
        red.backgroundColor = UIColor.red
        red.mask(CGRect(x: 50, y: 50, width: 50, height: 50), invert: true)
    }
}

extension UIView{

    func mask(_ rect: CGRect, invert: Bool = false) {
        let maskLayer = CAShapeLayer()
        let path = CGMutablePath()
        if (invert) {
            path.addRect(bounds)
        }
        path.addRect(rect)
        maskLayer.path = path
        if (invert) {
            maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
        }
        // Set the mask of the view.
        layer.mask = maskLayer
    }
}

666

感谢@arvidurs

答案 5 :(得分:0)

这是我的Swift 4.2解决方案,它允许拐角半径

extension UIView {

    func mask(withRect maskRect: CGRect, cornerRadius: CGFloat, inverse: Bool = false) {
        let maskLayer = CAShapeLayer()
        let path = CGMutablePath()
        if (inverse) {
            path.addPath(UIBezierPath(roundedRect: self.bounds, cornerRadius: cornerRadius).cgPath)
        }
        path.addPath(UIBezierPath(roundedRect: maskRect, cornerRadius: cornerRadius).cgPath)

        maskLayer.path = path
        if (inverse) {
            maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
        }

        self.layer.mask = maskLayer;
    }

}

答案 6 :(得分:0)

要反转遮罩,您可以使用类似

  1. 在这里,我有像

    这样的交叉矩形的面具
    <ul>
        <li><a href="#">item 1</a><p>description about item</p></li>
        <li><a href="#">item 2</a><p>description about item</p></li>
        <li><a href="#">item 3</a><p>description about item</p></li>
    </ul>
  2. 在这里,我在交叉的矩形周围添加第三个矩形 因此,使用.evenOdd会占用等于(新矩形-旧交叉矩形)的面积,换句话说,就是在交叉矩形的面积之外

     let crossPath =  UIBezierPath(rect: cutout.insetBy(dx: 30, dy: -5))
              crossPath.append(UIBezierPath(rect: cutout.insetBy(dx: -5, dy: 30)))
                let crossMask = CAShapeLayer()
                crossMask.path = crossPath.cgPath
                crossMask.backgroundColor = UIColor.clear.cgColor
                crossMask.fillRule = .evenOdd
    

enter image description here