Preface:

More and more applications, when waiting for the network to use the effect of blinking, so this effect, how to achieve? As I speak, the code is already on Github

Add overlay and dynamic effects

1. Obtain the control path

Get each control and find the path of the control (the outermost lines of the control). The original control mask is just a rectangle. For aesthetics, I recommend adding rounded corners to each control path

// Get the path of each child control for the mask layer
    // Add rounded corners
    UIBezierPath *defaultCoverblePath = [UIBezierPath bezierPathWithRoundedRect:subview.bounds cornerRadius:subview.frame.size.height/2.0/*subview.layer.cornerRadius*/];
    if ([subview isMemberOfClass:[UILabel class]] || [subview isMemberOfClass:[UITextView class]]) {
        defaultCoverblePath = [UIBezierPath bezierPathWithRoundedRect:subview.bounds cornerRadius:4];
    }
    UIBezierPath *relativePath = defaultCoverblePath;

    // Calculate the frame of subView relative to super view
    CGPoint offsetPoint = [subview convertRect:subview.bounds toView:view].origin; 
    [subview layoutIfNeeded];
    [relativePath applyTransform:CGAffineTransformMakeTranslation(offsetPoint.x, offsetPoint.y)];

    UIBezierPath *totalCoverablePath = [[UIBezierPath alloc] init];
    [totalCoverablePath appendPath:relativePath];
Copy the code

2. Add an overlay layer to show only the gradient layer of the path control

1. Add overlay layer to overlay control

2. Add a gradient layer to the overlay layer that blocks the control

3. Set mask for the gradient layer to display the gradient layer below the mask area (see below for principle)

    // Add overlay to block all controls (block the entire SuperView, including superView's child controls)
    self.viewCover.frame = CGRectMake(0.0, view.frame.size.width, view.frame.size.height);
    [view addSubview:self.viewCover];

// gradientLayer CAGradientLayer is a subclass of CALayer that generates gradientLayer
    CAGradientLayer *colorLayer = [CAGradientLayer layer];
    colorLayer.frame = (CGRect)self.view.bounds;

    colorLayer.startPoint = CGPointMake(1.4.0);
    colorLayer.endPoint = CGPointMake(1.4.0);
    
    // Color split line
    colorLayer.colors = @[(__bridge id) [UIColor colorWithRed:0 green:0 blue:0 alpha:0.03].CGColor,(__bridge id) [UIColor colorWithRed:0 green:0 blue:0 alpha:0.1].CGColor,(__bridge id) [UIColor colorWithRed:1 green:1 blue:1 alpha:0.02].CGColor, (__bridge id) [UIColor colorWithRed:0 green:0 blue:0 alpha:0.06].CGColor, (__bridge id) [UIColor colorWithRed:0 green:0 blue:0 alpha:0.04].CGColor];

    colorLayer.locations = @[
                             [NSNumber numberWithDouble:colorLayer.startPoint.x],
                             [NSNumber numberWithDouble:colorLayer.startPoint.x],
                             @0[NSNumber numberWithDouble:0.2],
                             [NSNumber numberWithDouble:1.2]];

    [self.viewCover.layer addSublayer:colorLayer];
    
    // Add mask to superview
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.path = totalCoverablePath.CGPath;
    maskLayer.fillColor = [UIColor whiteColor].CGColor;
    colorLayer.mask = maskLayer;
Copy the code

Principle:

The mask layer must have at least two layers. The upper layer is called “mask layer” and the lower layer is called “masked layer”. Only where the two layers overlap will be shown. This means that objects in the mask layer are “transparent” and can be seen in the masked layer, while objects without objects are opaque and the corresponding positions of objects in the masked layer are invisible. Its principle is: the upper layer is the mask layer, the lower layer is the masked layer. Images on the mask layer are not displayed by themselves. It only acts as a conduit for light. If the mask layer is a perfect circle, then the light will pass through the circle and hit the mask layer below, showing only a circular shape. If there is nothing on the mask layer, then no light can penetrate below, and the layer underneath the mask will show nothing.

The above code results in the following effect:

3. Add dynamic effects to the gradient layer

    / / animation animate
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"locations"];
    animation.fromValue = colorLayer.locations;
    animation.toValue = @[
                          @0The @1The @1The @1.2The @1.2];
    animation.duration = 0.7;
    animation.repeatCount = HUGE;
    [animation setRemovedOnCompletion:NO];
    // Add an animation for the gradient layer
    [colorLayer addAnimation:animation forKey:@"locations-layer"];
Copy the code

Remove all overlay and effect

    // Remove dynamic effects and layers
    [self.colorLayer removeAllAnimations];
    [self.colorLayer removeFromSuperlayer];
    [self.maskLayer removeFromSuperlayer];
    // Remove the overlay of the control
    [self.viewCover removeFromSuperview];
Copy the code

In this way, I have completed the Loding diagram of a mainstream APP. I also made a special package for this code, and the code has been put on Github




Welcome to the technical public account “Programmer Guru Show”