iOS Animation-Window Scenery (3·End)

Posted Jun 28, 20206 min read

This article is the third in a series of articles.

Friends who have seen the previous article already know that the "view" in the title refers to view, and the "window" refers to view.mask, and the window scene is to sort out the mask and mask animation. If you are not familiar with the mask of iOS, it is recommended to take a look at Part 1 .

In the first two articles, we introduced some usages of mask and mask animation.

This article is the finale, let s practice an effect,
Also borrow this effect to remind everyone of a simple truth:complex effects can be equivalent to a combination of simple effects.

  1. Effect

This effect is shown in the following animation:

3-wave.gif

We intercept a more representative frame, as shown in the following figure:

3-wave.jpg

As you can see from the picture, the wave is composed of two colors, and the colors of each part are different.

This effect looks a bit complicated, if you are not familiar with the mask, you may have no idea for a while.
But friends who have seen the first two articles may have secretly thought, is the window moving? Still moving? Will there be multiple sets of window views?

So next, let's take a look at the principle through a simple effect.

Note:The realization of the wave animation has little to do with this article, and it will not be described in this article.
There is a mature wave animation tutorial on the Internet, and the WaveView class in the demo of this article also has a brief comment.

  1. A simple effect

This effect is shown below:

3-image-mix.jpg

As you can see from the picture, a part of a black and white picture is in color.
Of course, we can achieve this effect through image processing, but in this article, we still use the mask method to achieve.

Let's recall a picture from the previous article:

2-circle2-ios.jpg

By adding a round mask to frontView, the effect in the figure is formed.

Maybe some friends have thought that replacing the backView image in the above picture with the black and white picture same as the frontView is not the effect of this example, as shown in the following figure:

3-image.jpg

In other words, this effect looks like a part of the black and white picture has become color,
But in fact, only two pictures with the same content overlap, the black and white picture is behind, the color picture is in front, and the front color picture is applied with a round mask.

This effect is very simple, but it makes us aware of one thing:it looks like a picture, in fact, it may be a combination of multiple pictures.

That being the case, is the wave with different colors in each part of the wave animation in this article really a wave?

That's right, the waves in this example are also composed of multiple waves. Next, let's take a closer look.

Second, multiple scenes in one

Like the overlapping effect of black and white and color pictures, multi-color waves are also composed of a group of overlapping wave views.

The wave of each layer of view has only one color, and the wave animation of each layer of view is consistent. For each frame, all waves are completely coincident.

Each wave view has its own mask. Under the control of the masks, each wave view only shows a part of the wave. The multi-colored waves we see are the combination of the visible parts of each wave view.

We take two layers to illustrate, as shown below:

3-mask2.jpg

As you can see from the figure, the red wave view on the white background has an upper semicircular mask, and the blue wave view on the black background has a lower semicircular mask. The wave progress of the two views is exactly the same, and the combination becomes the rightmost effect.

After puncturing this layer of window paper, the principle is actually so simple.

Knowing the principle, in fact, you can do it yourself to achieve the effect,
Of course, if you are not in a hurry, let's go through the process together.

Third, create a 4-layer view

This step is very simple. Create a 4-layer view with a completely consistent frame. In this example, WaveView is used as the view.
Set different background colors(black, white) and wavy colors(red, blue) as needed.

After this step, the 4-layer wave view is shown in the figure:

3-view.jpg

The schematic code is as follows:

//A3WaveViewController
private func addSubViews() {
    //Upper big semicircle view
    view.addSubview(bigTopView)
    //Upper small semicircle view
    view.addSubview(smallTopView)
    //Lower big semicircle view
    view.addSubview(bigBottomView)
    //Lower small semicircle view
    view.addSubview(smallBottomView)
}

Fourth, set the mask for the 4-layer view

This step is to make a suitable mask.
In this example, HalfCircleView is used as a mask, and two large semicircles and two small semicircles are set for each layer view.

After this step, the four-layer view is under the influence of mask as shown in the figure below. You can compare it with the four views in the previous figure:

3-mask.jpg

The schematic code is as follows:

//A3WaveViewController
private func makeLayout() {
    //Set the mask of 4 views

    //Large upper semicircle
    let width:CGFloat = 200
    let marginX =(UIScreen.main.bounds.width-width)/2
    bigTopView.frame = CGRect(x:marginX, y:200, width:width, height:200)
    //Large upper semicircle mask
    let bigTopMask = HalfCircleView()
    bigTopMask.part = .top
    bigTopMask.frame = CGRect(x:0, y:0, width:bigTopView.bounds.width, height:bigTopView.bounds.height/2)
    bigTopView.mask = bigTopMask

    //Small upper semicircle(the radius is half of the large semicircle)
    smallTopView.frame = bigTopView.frame
    //Small upper semicircle mask
    let smallTopMask = HalfCircleView()
    smallTopMask.part = .top
    smallTopMask.frame = CGRect(x:smallTopView.bounds.width/4,
                                y:smallTopView.bounds.height/4,
                                width:smallTopView.bounds.width/2,
                                height:smallTopView.bounds.height/4)
    smallTopView.mask = smallTopMask

    //big lower semicircle
    bigBottomView.frame = bigTopView.frame
    //big lower semicircle mask
    let bigBottomMask = HalfCircleView()
    bigBottomMask.part = .bottom
    bigBottomMask.frame = CGRect(x:0,
                                 y:bigBottomView.bounds.height/2,
                                 width:bigBottomView.bounds.width,
                                 height:bigBottomView.bounds.height/2)
    bigBottomView.mask = bigBottomMask

    //Small lower semicircle
    smallBottomView.frame = bigBottomView.frame
    //Small lower half circle mask
    let smallBottomMask = HalfCircleView()
    smallBottomMask.part = .bottom
    smallBottomMask.frame = CGRect(x:smallBottomView.bounds.width/4,
                                   y:smallBottomView.bounds.height/2,
                                   width:smallBottomView.bounds.width/2,
                                   height:smallBottomView.bounds.height/4)
    smallBottomView.mask = smallBottomMask
}

Fifth, let the 4 layer view perform animation consistently

In order to make the wave animation of each layer completely consistent, we start a CADisplayLink externally to change the progress of the 4 wave views at the same time(in the previous figure, when the progress is 0.5, it is used as an example).

Also achieved the effect of the beginning of this article:

3-wave.gif

The schematic code is as follows:

//A3WaveViewController
func start() {
    if let displayLink = displayLink {
        displayLink.invalidate()
        self.displayLink = nil
        progress = 0
    }
    //Start CADisplayLink
    let displayLink = CADisplayLink(target:WeakProxy(self), selector:#selector(work))
    displayLink.add(to:RunLoop.current, forMode:.common)
    self.displayLink = displayLink
}

@objc private func work() {
    if progress <1 {
        progress += 0.0025
        progress = min(progress, 1)
    } else {
        progress = 0
    }
    //Set the progress of 4 wave views when CADisplayLink is called back
    bigTopView.progress = progress
    bigBottomView.progress = progress
    smallTopView.progress = progress
    smallBottomView.progress = progress
}

At this point, the effect is complete.

Of course, you can replace WaveView with your own animated view, change the number of views, use other masks, etc.
To achieve the splicing effect you want.

Of course, the performance of this animation method has not been evaluated and may not be suitable for use in a production environment.
This example is more to remind everyone of a simple truth:

Complex animation can be equivalent to a combination of simple animation; as long as it is still complex, you can continue to split it.

If you want to split and don t know where to start, you can try this:

As long as the animation of one part is different from other parts, it can be split.

Once simple animations are implemented, they are combined to complete complex animations.

Combination is our commonly used method, such as the double wave in the figure below:

3-2wave.gif

Of course we can directly write a double wave class, but we can also combine two wave views to form a double wave.

The combination looks a bit silly, but it also has its advantages,
For example, when the effect we want to reuse is very complicated and difficult to rewrite, or if we don't have the source code of the effect at all, combination may be the easiest way.

end

This series only shows the common mask effect, hanging one thousand and ten thousand. After all, there are unlimited windows, unlimited sceneries, unlimited combinations, and unlimited effects.

If you find an interesting mask animation, please leave a message in the comment area and hope we can make progress together.

All the examples in this article have complete code in GitHub Library .

This series is over, thank you for reading.

Portal