Question

I have a UIView that draws different shapes. I can make a hole in my image to have it transparent, working fine, but the hole is only square,

//hole
CGRect holeRectValue = CGRectMake(300, 40, 80, 100);

CGRect holeRectIntersection = CGRectIntersection( holeRectValue, rect );
[[UIColor clearColor] setFill];
UIRectFill(holeRectIntersection);

Now I need to make the hole in the image but not as a rect, as the shape of my drawn figure,

Here is the code:

- (id)initWithFrame:(CGRect)frame forNode0:(CGPoint)node0 forNode1:(CGPoint)node1 fornode2:(CGPoint)node2 fornode3:(CGPoint)node3 fornode4:(CGPoint)node4 fornode5:(CGPoint)node5 fornode6:(CGPoint)node6 fornode7:(CGPoint)node7 fornode8:(CGPoint)node8 fornode9:(CGPoint)node9
{
    self = [super initWithFrame:frame];
    if (self) {
        self.opaque = NO;
        self.node0Pos = node0;
        self.node1Pos = node1;
        self.node2Pos = node2;
        self.node3Pos = node3;
        self.node4Pos = node4;
        self.node5Pos = node5;
    }
    return self;
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    //bgnd
    UIGraphicsBeginImageContext(self.frame.size);
    [[UIImage imageNamed:@"cat.jpeg"] drawInRect:self.bounds];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [[UIColor colorWithPatternImage:image] setFill];

    // Drawing code
    UIRectFill(rect);

    // Drawing code
    //1. begin new path
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextBeginPath(context);
    //2. move to initial starting point
    CGContextMoveToPoint(context, self.node0Pos.x, self.node0Pos.y);
    //3. add lines defining shape
    CGContextAddLineToPoint(context, self.node1Pos.x, self.node1Pos.y);
    CGContextAddLineToPoint(context, self.node2Pos.x, self.node2Pos.y);
    CGContextAddLineToPoint(context, self.node3Pos.x, self.node3Pos.y);
    CGContextAddLineToPoint(context, self.node4Pos.x, self.node4Pos.y);
    CGContextAddLineToPoint(context, self.node5Pos.x, self.node5Pos.y);

    //4. optionally close path
    CGContextClosePath(context);

    CGColorRef color;

    //5. draw path
    color = [UIColor colorWithRed:1 green:0 blue:228/255.0f alpha:0.5].CGColor;

    //CGContextSetFillColor(context, color);
    CGContextSetFillColorWithColor(context, color);
    CGContextDrawPath(context, kCGPathFill);

    //
    //hole
    CGRect holeRectValue = CGRectMake(300, 40, 80, 100);

    CGRect holeRectIntersection = CGRectIntersection( holeRectValue, rect );
    [[UIColor clearColor] setFill];
    UIRectFill(holeRectIntersection);
}

So how do I make the "hole" with my actual context path?

P.S. I was doing some masking, but it leaves a white line around the hole, so I need to avoid this.

Was it helpful?

Solution

[[UIColor clearColor] setFill];
UIRectFill(holeRectIntersection);

This doesn’t do anything—drawing with a clear color is effectively a no-op. What you most likely want to do is add the rectangle you’re trying to cut out as part of the path you’re creating, i.e. inserting a call to CGContextAddRect before your CGContextClosePath. See Filling a Path in the Quartz 2D Programming Guide.

OTHER TIPS

I believe what you're looking for is the CALayer.mask property. To create a "hole", you would generate a CALayer object with an alpha channel in the shape of the hole you want to make, and then apply it to the view you want to punch the hole in.

In semi-pseudocode:

CALayer *holeMask;
UIView *myView;

// 
// Build the holeMask object via whatever means, 
// and set myView to the target view that you want
// to punch the hole in...
//

myView.layer.mask = holeMask
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top