Crop a CAShapeLayer retrieving the external path

后端 未结 2 613
盖世英雄少女心
盖世英雄少女心 2020-12-02 19:38

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

相关标签:
2条回答
  • 2020-12-02 20:04

    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]];
    
    0 讨论(0)
  • 2020-12-02 20:07

    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)
        }
    }
    
    0 讨论(0)
提交回复
热议问题