How to add a circular mask to a UIImageview and change the frame and centers while doing so?
Asked Answered
R

2

11

I would like to add a circular mask to UIImageVIew. Here is the function that am using to add the mask..

- (void) addMaskToBounds:(CGRect) maskBounds
{
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];

    CGPathRef maskPath = CGPathCreateWithEllipseInRect(maskBounds, NULL);
    maskLayer.bounds = maskBounds;
    [maskLayer setPath:maskPath];
    [maskLayer setFillColor:[[UIColor blackColor] CGColor]];
    maskLayer.position = CGPointMake(maskBounds.size.width/2, maskBounds.size.height/2);

    [self.imageView.layer setMask:maskLayer];
}

Am able to add the mask but the problem occurs since am changing the image frame and center along with it. The image is enlarged and made small based on the user actions. Hence I would have to add the mask twice when small and when enlarged. So Since am animating the frame change, while animating the image become distorted, or displaced. How do I overcome this ?

I guess its best explained with an example project. Here I have created a Demo project https://github.com/akshaynhegde/MaskImage on GitHub, just run it to see my problem and let me know how resolve the problem.

Reimer answered 9/3, 2013 at 5:43 Comment(1)
This has been asked before: #12564836Fanti
S
23

Hope this will help

    CAShapeLayer *circle = [CAShapeLayer layer];
    // Make a circular shape
    UIBezierPath *circularPath=[UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, _imgView.frame.size.width, _imgView.frame.size.height) cornerRadius:MAX(_imgView.frame.size.width, _imgView.frame.size.height)];

    circle.path = circularPath.CGPath;

    // Configure the apperence of the circle
    circle.fillColor = [UIColor blackColor].CGColor;
    circle.strokeColor = [UIColor blackColor].CGColor;
    circle.lineWidth = 0;

    imgViewToClipCircular.layer.mask=circle;
Sprint answered 16/6, 2014 at 12:4 Comment(2)
This doesn't solve the initial question of how to animate frame changes to UIImageView when using a mask at all...Seeseebeck
I found this code very handy because I needed an off-center circular mask for a view I was creating. First I used layer.cornerRadius to make the view circular in Interface Builder. Then I used this code with a negative Y value in the Bezier path to create a mask for it. The resulting shape looks a lot like an American football, which is what I needed.Verine
R
4

Ok, so since the center in my case changes, using the mask is not ging to help. So the easy and clean way is to have a custom UiImageView and clip the draw path.

So for that, subclass UIView and draw the image inside it and clip the path. Here is the overriden the drawRect function,

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextAddEllipseInRect(context, self.bounds);
    CGContextClip(context);
    //The subclass of UIView has a UIImageview as property
    [_image drawInRect:rect];    
}

FYI, you can not subclass UIImageView itself and override drawRect , coz it won't call the drawRect,

The UIImageView class is optimized to draw its images to the display. UIImageView will not call drawRect: a subclass. If your subclass needs custom drawing code, it is recommended you use UIView as the base class.

Reimer answered 15/3, 2013 at 4:15 Comment(3)
The custom UIImageView solution was what I was previously using, so this solution worked was appropriate for me. It also looks closer to what iOS 7 doesVeery
You can change centre of mask layer also.Sprint
Note that your comment is not quite correct -- this subclass of UIView must have a UIImage as a property, not a UIImageViewEscobedo

© 2022 - 2024 — McMap. All rights reserved.