3

There are some answers for objective c but did not find any regarding swift.

I would like to create a dark view with transparent circle in middle so that user can see the subview and interact with it. How can I implement that using swift.

More precisely I'm looking for a result like whatsapp profile picture implementation. There is this transparent circle in the middle and the user can see the picture and scroll for instance.

Thanks for your help guys!

Sam
  • 1,101
  • 2
  • 13
  • 26

2 Answers2

4

Cyril's answer translated to swift to prevent extra-typing:

    func circularOverlayMask() -> UIImage {
        let bounds = self.view.bounds
        let width = bounds.size.width
        let height = bounds.size.height
        let diameter = width
        let radius = diameter / 2
        let center = CGPointMake(width / 2, height / 2)

        // Create the image context
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0)

        // Create the bezier paths
        let clipPath = UIBezierPath(rect: bounds)
        let maskPath = UIBezierPath(ovalInRect: CGRectMake(center.x - radius, center.y - radius, diameter, diameter))

        clipPath.appendPath(maskPath)
        clipPath.usesEvenOddFillRule = true

        clipPath.addClip()
        UIColor(white: 0, alpha: 0.5).setFill()
        clipPath.fill()

        let finalImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()

        return finalImage
    }
Bruno Galinari
  • 155
  • 2
  • 12
2

Here is a method I use in my projects to create circular masks (this is not in Swift but easily translatable):

- (UIImage *)circularOverlayMask
{
    // Constants
    CGRect bounds = self.navigationController.view.bounds;
    CGFloat width = bounds.size.width;
    CGFloat height = bounds.size.height;
    CGFloat diameter = width - (INNER_EDGE_INSETS * 2);
    CGFloat radius = diameter / 2;
    CGPoint center = CGPointMake(width / 2, height / 2);

    // Create the image context
    UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0);

    // Create the bezier paths
    UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:bounds];
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(center.x - radius, center.y - radius, diameter, diameter)];

    [clipPath appendPath:maskPath];
    clipPath.usesEvenOddFillRule = YES;

    [clipPath addClip];
    [[UIColor colorWithWhite:0 alpha:0.5f] setFill];
    [clipPath fill];

    UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return finalImage;
}

I basically create a subview that I add above the image scrollView, like this:

UIImageView *maskView = [[UIImageView alloc] initWithImage:[self overlayMask]];
maskView.userInteractionEnabled = NO;
[self.view insertSubview:maskView aboveSubview:_scrollView];

Hope that helps.

(Originally found in DZNPhotoPickerController)

Cyril
  • 1,649
  • 1
  • 17
  • 32
  • Thanks Cyril, do you know how can I create an image object with what is showing in the circle ( as part of a bigger image which is behind the mask) ? – Sam Feb 26 '15 at 09:56
  • You should have a look to DZNPhotoPickerController implementation in the ```editedImage``` method : https://github.com/dzenbot/DZNPhotoPickerController/blob/3bba17c70b29ca44313b30cff9b4eefe3bc82389/Source/Classes/Editor/DZNPhotoEditorViewController.m#L481 – Cyril Feb 26 '15 at 10:49