Crop a CAShapeLayer retrieving the external path

时光毁灭记忆、已成空白 提交于 2019-12-17 10:35:16

问题


I am trying to crop a layer with other, but, instead of creating a mask (B) and crop the layer (A) getting a cropped layer A with the shape of B, I want to get a layer with shape A and a 'hole' created by cropping with layer B.

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

How can I get the cropped layer A?


回答1:


You have to create a mask that covers the area that you want to keep. This can be done by using an even-odd fill rule and create a path for a shape layer with both rectangles. You can create the shape like this (where the two rectangles would be your two frames). Then you set this as the mask to get the result that you are after.

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]];



回答2:


Swift 3.0 solution:

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


来源:https://stackoverflow.com/questions/10856353/crop-a-cashapelayer-retrieving-the-external-path

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!