2012-06-01 5 views
7

Ich versuche, eine Ebene mit anderen zu beschneiden, aber anstatt eine Maske (B) zu erstellen und die Ebene (A) beschneiden eine zugeschnittene Ebene A mit der Form von B, ich will eine Schicht mit Form A und ein ‚Loch‘ geschaffen zu erhalten, indemCrop ein CAShapeLayer beim Abrufen des externen Pfades

*************    ***Layer A*** 
* Layer A *    ************* 
* ***** *    **** ***** 
* * B * *  ->  **** ***** Layer A without shape B 
* ***** *    **** ***** 
*   *    ************* 
*************    ************* 

mit Schicht B. Zuschneiden Wie kann ich die beschnittene Schicht A bekommen?

Antwort

20

Sie müssen eine Maske erstellen, die den Bereich abdeckt, den Sie behalten möchten. Dies kann durch Verwenden einer geraden-ungeraden Füllregel und Erstellen eines Pfads für eine Formebene mit beiden Rechtecken erfolgen. Sie können die Form wie folgt erstellen (wobei die zwei Rechtecke Ihre zwei Rahmen wären). Dann legen Sie dies als Maske fest, um das gewünschte Ergebnis zu erhalten.

CAShapeLayer *maskWithHole = [CAShapeLayer layer]; 

// Both frames are defined in the same coordinate system 
CGRect biggerRect = CGRectMake(30, 50, 120, 200); 
CGRect smallerRect = CGRectMake(80, 100, 50, 80); 

UIBezierPath *maskPath = [UIBezierPath bezierPath]; 
[maskPath moveToPoint:CGPointMake(CGRectGetMinX(biggerRect), CGRectGetMinY(biggerRect))]; 
[maskPath addLineToPoint:CGPointMake(CGRectGetMinX(biggerRect), CGRectGetMaxY(biggerRect))]; 
[maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(biggerRect), CGRectGetMaxY(biggerRect))]; 
[maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(biggerRect), CGRectGetMinY(biggerRect))]; 
[maskPath addLineToPoint:CGPointMake(CGRectGetMinX(biggerRect), CGRectGetMinY(biggerRect))]; 

[maskPath moveToPoint:CGPointMake(CGRectGetMinX(smallerRect), CGRectGetMinY(smallerRect))]; 
[maskPath addLineToPoint:CGPointMake(CGRectGetMinX(smallerRect), CGRectGetMaxY(smallerRect))]; 
[maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(smallerRect), CGRectGetMaxY(smallerRect))]; 
[maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(smallerRect), CGRectGetMinY(smallerRect))]; 
[maskPath addLineToPoint:CGPointMake(CGRectGetMinX(smallerRect), CGRectGetMinY(smallerRect))]; 

[maskWithHole setPath:[maskPath CGPath]]; 
[maskWithHole setFillRule:kCAFillRuleEvenOdd]; 
[maskWithHole setFillColor:[[UIColor orangeColor] CGColor]]; 
0

Swift 3.0 Lösung:

class MakeTransparentHoleOnOverlayView: UIView { 

    @IBOutlet weak var transparentHoleView: UIView! 

    // MARK: - Drawing 

    override func draw(_ rect: CGRect) { 
     super.draw(rect) 

     if self.transparentHoleView != nil { 
      // Ensures to use the current background color to set the filling color 
      self.backgroundColor?.setFill() 
      UIRectFill(rect) 

      let layer = CAShapeLayer() 
      let path = CGMutablePath() 

      // Make hole in view's overlay 
      // NOTE: Here, instead of using the transparentHoleView UIView we could use a specific CFRect location instead... 
      path.addRect(transparentHoleView.frame) 
      path.addRect(bounds) 

      layer.path = path 
      layer.fillRule = kCAFillRuleEvenOdd 
      self.layer.mask = layer 
     } 
    } 

    override func layoutSubviews() { 
     super.layoutSubviews() 
    } 

    // MARK: - Initialization 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
    } 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
    } 
}