Search code examples
iosiphonegraphicscalayer

Borders around a CALayer mask


I'll start off showing you what I need the end product to look like.

Final Product

I'm using a cocoapod called BAFluidView that basically simulates the motion of fluid in a container. The developer provided a guide(see the "Use As a Layer" section) showing how you could add a mask to the fluidView's layer for an effect.

So far, I can mask the fluiview with any UIImage I add to the project. I am, however, facing a problem trying to add a white border around the outline of the water droplet and could use any help I can get.

Thanks very much!


Solution

  • This is what I would call the "brute force" method. Create an image to use as the mask and create a second image to use as the outline.

    Note: these images have alpha channels, so it may not be clear unless/until you download them. The checkerboard images shows how they look in GIMP.

    Mask Image (which I took from the BAFluidView example):

    enter image description here - enter image description here

    White outline image (trust me, it's here... just click below):

    enter image description here - enter image description here

    and the code:

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
    
        // load mask and outline
        UIImage *maskingImage = [UIImage imageNamed:@"blueDrop"];
        UIImage *outlineImage = [UIImage imageNamed:@"whiteOutlineThin"];
    
        // define rect equal to size of mask image
        CGRect rfv = CGRectMake(0, 0, maskingImage.size.width, maskingImage.size.height);
    
        // instantiate BAFluidView
        BAFluidView *fluidView = [[BAFluidView alloc] initWithFrame:rfv startElevation:@0.3];
        fluidView.fillColor = [UIColor colorWithHex:0x092eee];
        [fluidView fillTo:@0.90];
        [fluidView startAnimation];
    
        // if you want the "droplet" filled with a color
        //  fluidView.backgroundColor = [UIColor yellowColor];
    
        // instantiate a couple CALayer objects
        CALayer *maskingLayer = [CALayer layer];
        CALayer *outlineLayer = [CALayer layer];
    
        // set size to match mask
        maskingLayer.frame = rfv;
        outlineLayer.frame = rfv;
    
        // set mask layer content to mask image
        [maskingLayer setContents:(id)[maskingImage CGImage]];
    
        // give the mask layer to BAFluidView
        [fluidView.layer setMask:maskingLayer];
    
        // set outline layer content to outline image
        [outlineLayer setContents:(id)[outlineImage CGImage]];
    
        // create a "container" view
        UIView *containerView = [[UIView alloc] initWithFrame:rfv];
    
        // add the outline layer
        [containerView.layer addSublayer:outlineLayer];
    
        // add the BAFluidView
        [containerView addSubview:fluidView];
    
        // add the container view to the screen / main view
        [self.view addSubview:containerView];
    
        // position the view with constraints...
        containerView.translatesAutoresizingMaskIntoConstraints = NO;
    
        [containerView.widthAnchor constraintEqualToConstant:rfv.size.width].active = YES;
        [containerView.heightAnchor constraintEqualToConstant:rfv.size.height].active = YES;
        [containerView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES;
        [containerView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor].active = YES;
    
    }
    

    Screen-cap of the result:

    enter image description here

    You could automate it, and make the process a bit more "elegant" and flexible, by using just the Mask image and generating the outline on-the-fly via code - scale the mask image up by a little bit and then mask it with the original sized image, for example.