2015-04-22 25 views
6

Sto usando CAShapeLayer.path e CALayer.mask per impostare la maschera immagine, posso ottenere il "set differenza" ed effetto "unione" per CGPath impostandoCome ottenere l'intersezione di due CGPath?

maskLayer.fillRule = kCAFillRuleEvenOdd/kCAFillRuleZero 

Tuttavia, come posso ottenere l'intersezione di due percorsi? Non riesco a raggiungerlo con la regola pari-dispari

Ecco un esempio: enter image description here

let view = UIImageView(frame: CGRectMake(0, 0, 400, 400)) 
view.image = UIImage(named: "scene.jpg") 
let maskLayer = CAShapeLayer() 
let maskPath = CGPathCreateMutable()  
CGPathAddEllipseInRect(maskPath, nil, CGRectOffset(CGRectInset(view.bounds, 50, 50), 50, 0)) 
CGPathAddEllipseInRect(maskPath, nil, CGRectOffset(CGRectInset(view.bounds, 50, 50), -50, 0)) 
maskLayer.path = maskPath 
maskLayer.fillRule = kCAFillRuleEvenOdd 
maskLayer.path = maskPath 
view.layer.mask = maskLayer 

come posso ottenere la parte centrale di essa da mostrare? Voglio dire, solo la parte centrale (che è vuota nella vista di esempio).

Posso farlo facilmente con software di progettazione vettoriale come AI, quindi penso che ci sia un modo per gestire.

+0

Vedi http://robnapier.net/clipping-cgrect-cgpath per una tecnica. La stessa tecnica può essere utilizzata per più CGPath (in realtà si applica a qualsiasi cosa tu possa disegnare). –

risposta

7
extension UIImage { 
    func doubleCircleMask(#circleSize:CGFloat)-> UIImage { 
     let rectangle = CGRectMake(0, 0, size.width, size.height) 
     UIGraphicsBeginImageContext(size) 
     let x = size.width/2-circleSize/2 
     let y = size.height/2-circleSize/2 
     let offset = circleSize/4 
     let shape1 = UIBezierPath(roundedRect: CGRectMake(x-offset, y, circleSize, circleSize), cornerRadius: circleSize/2) 
     shape1.appendPath(UIBezierPath(roundedRect: CGRectMake(x+offset, y, circleSize, circleSize), cornerRadius: circleSize/2)) 
     shape1.addClip() 
     drawInRect(rectangle) 
     let result = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 
     return result 
    } 
    func doubleCircleIntersectionMask(#circleSize:CGFloat)-> UIImage { 
     let rectangle = CGRectMake(0, 0, size.width, size.height) 
     UIGraphicsBeginImageContext(size) 
     let x = size.width/2-circleSize/2 
     let y = size.height/2-circleSize/2 
     let offset = circleSize/4 
     let shape1 = UIBezierPath(roundedRect: CGRectMake(x-offset, y, circleSize, circleSize), cornerRadius: circleSize/2) 
     let shape2 = UIBezierPath(roundedRect: CGRectMake(x+offset, y, circleSize, circleSize), cornerRadius: circleSize/2) 
     shape1.addClip() 
     shape2.addClip() 
     drawInRect(rectangle) 
     let result = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 
     return result 
    } 

} 

Testing

let myPicture = UIImage(data: NSData(contentsOfURL: NSURL(string: "http://i.stack.imgur.com/Xs4RX.jpg")!)!)! 

let myPictureUnion = myPicture.doubleCircleMask(circleSize: 300) 

let myPictureIntersection = myPicture.doubleCircleIntersectionMask(circleSize: 300) 

enter image description here

+0

Sì, l'uso di 'UIBezierPath' invece di' CGPath' rende possibile fare multi-clip invece di essere limitato da fillRule. Molte grazie. – duan

+0

Per essere chiari, questo può essere fatto anche con 'CGPath's, quindi il commento su solo' UIBezierPath's che lo rende possibile non è accurato. Basta controllare questo [Playground] (https://gist.github.com/henrinormak/c6f792ed269723def347) Ho scritto usando la stessa logica esatta di questa risposta, ma usando 'CGContext' e' CGPath' invece –

+0

@HenriNormak cool. – duan