2012-06-01 17 views
7

Sto cercando di ritagliare un livello con altro, ma, invece di creare una maschera (B) e ritagliare il livello (A) ottenendo un livello ritagliato A con la forma di B, voglio per ottenere un livello di forma a e un 'buco' creato da ritagliare con lo strato B.Ritaglia un CAShapeLayer che recupera il percorso esterno

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

Come posso ottenere lo strato ritagliata a?

risposta

20

È necessario creare una maschera che copra l'area che si desidera mantieni. Questo può essere fatto usando una regola di riempimento dispari e creare un percorso per un livello forma con entrambi i rettangoli. Puoi creare la forma in questo modo (dove i due rettangoli sarebbero i tuoi due fotogrammi). Quindi lo imposti come maschera per ottenere il risultato che cerchi.

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 soluzione:

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) 
    } 
} 
Problemi correlati