This article is the third in a series.

For those of you who read the last article, you already know that “view” in the title refers to view, and “window” refers to view.mask. If you’re not familiar with masks on iOS, I recommend reading the first article.

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

This article as the end, we will realize an effect practice, also by this effect, let us recall a simple truth: complex effects, can be equivalent to the combination of simple effects.

A, effects,

The effect can be seen in the GIF below:

We captured a representative frame, as shown below:

As you can see from the picture, waves are made up of two colors, each part of which is different in color.

This effect looks a bit complicated, and if you are not familiar with masks, you may lose your train of thought for a while. But read the first two friends, may have secretly thought, is the window moving? Or is the scene moving? Will there be multiple Windows?

So let’s see how this works with a simple effect.

Note: The implementation of wave animation is not relevant to this article and will not be described in this article. Mature wave animation tutorials are available online, and the WaveView class is briefly commented on in this demo.

Two, a simple effect

The effect is shown below:

As can be seen from the picture, part of a black and white picture is colored. We can certainly do this with image manipulation, but in this article, we’ll use masks.

Let’s recall one of the images from the previous article:

By adding a circular mask to the frontView, the effect is created.

Maybe some friends have thought of changing backView into black and white pictures like frontView in the figure above, which is the effect of this example, as shown below:

In other words, the effect appears to be that part of the black and white image turns into color, but it’s really just two images with the same content overlapping, with the black and white image behind, the color image in front, and the color image in front, with a circular mask applied.

The effect is simple, but it makes us realize one thing: what looks like one image can actually be a combination of multiple images.

In this case, is the wave with different colors in the wave animation in this paper really just a wave?

Yes, the wave in this case is also a combination of multiple waves, so let’s look at it in detail.

Three, the integration of multiple scenes

Like the overlapping effect of black and white and color images, multicolor waves are created by combining a set of overlapping wave views.

The waves of each layer of view have only one color, the wave animation of each layer of view is the same, and for each frame, all the waves are exactly the same.

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

Let’s take two layers to indicate, as shown in the figure below:

As can be seen from the figure, the red wave view on a white background has an upper semicircle mask, and the blue wave view on a black background has a lower semicircle mask. The wave progress of the two views is exactly the same, and after combination, it becomes the effect on the right.

Poke through this window, in fact, the principle is so simple.

Know the principle, in fact, we can go to their own hands to achieve the effect, of course, if there is no hurry, then let’s go through the process again.

Create 4 layers of views

This step is very simple, create a 4 layer view with exactly the same frame, in this case use WaveView as the view, set different background colors (black, white) and wave colors (red, blue) as needed.

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

The schematic code is as follows:

// A3WaveViewController
private func addSubViews(a) {
    // Create a semicircle view
    view.addSubview(bigTopView)
    // Create a small semicircle view
    view.addSubview(smallTopView)
    // Lower the semicircle view
    view.addSubview(bigBottomView)
    // Create a small semicircle view
    view.addSubview(smallBottomView)
}
Copy the code

5. Set mask for layer 4 view

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

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

The schematic code is as follows:

// A3WaveViewController
private func makeLayout(a) {
    // 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 (radius is half of larger 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 half circle
    bigBottomView.frame = bigTopView.frame
    // Large 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 half circle
    smallBottomView.frame = bigBottomView.frame
    // small lower semicircle 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
}

Copy the code

6. Animate all views on layer 4 in unison

To make the wave animations perfectly consistent across the layers, we launched a CADisplayLink externally to change the progress of all four wave Views at the same time (the previous figure used progress of 0.5 as an example).

This has achieved the effect of the beginning of this article:

The schematic code is as follows:

// A3WaveViewController
func start(a) {
    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(a) {
    if progress < 1 {
        progress += 0.0025
        progress = min(progress, 1)}else {
        progress = 0
    }
    // When CADisplayLink calls back, set the progress of 4 wave Views
    bigTopView.progress = progress
    bigBottomView.progress = progress
    smallTopView.progress = progress
    smallBottomView.progress = progress
}
Copy the code

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 desired Mosaic effect.

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

Complex animation can be equivalent to the combination of simple animation; As long as it’s complicated, you can keep breaking it up.

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

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

Simple animations, once implemented, can be combined to create complex animations.

Combinations are commonly used, such as the double wave shown below:

We could of course just write a double wave class, but we could also combine two wave views to form a double wave.

Composition may seem silly, but it has its advantages. For example, when the effect we want to reuse is complex and hard to rewrite, or we don’t have the source code for that effect at all, composition may be the easiest way.

The end of the

This series just shows the common mask effect, hang a thousand, after all, the window is infinite, the scene is infinite, the combination is infinite, the effect is infinite.

If you find an interesting mask animation, feel free to leave a comment in the comments section. May we make progress together.

The complete code for all of this article’s examples is available in the GitHub repository.

This concludes the series. Thank you for reading.

portal

  • Making library
  • IOS Animations – Windows Part 1
  • IOS Animation – Windows Part 2