Инверсная маска iOS в drawRect
С помощью приведенного ниже кода я успешно маскирую часть моего рисунка, но это инверсия того, что я хочу замаскировать. Это маскирует внутреннюю часть чертежа, где я хотел бы замаскировать внешнюю часть. Есть ли простой способ инвертировать эту маску?
myPath
ниже - UIBezierPath
.
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGMutablePathRef maskPath = CGPathCreateMutable();
CGPathAddPath(maskPath, nil, myPath.CGPath);
[maskLayer setPath:maskPath];
CGPathRelease(maskPath);
self.layer.mask = maskLayer;
Ответы
Ответ 1
При четном заполнении слоя формы (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;
Ответ 2
Для 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;
}
Ответ 3
На основании принятого ответа, здесь еще один mashup в 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;
}
Ответ 4
Для 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;
}
Ответ 5
Вот мое решение 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
Swift 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