11
头图

Before, I introduced several ways to use pure CSS to achieve wave effects. There are two related articles about them:

This article will introduce another wave effect using CSS, which is very interesting.

Speaking of Realizing the Area of Triangle with Curved Side by Definite Integral

Before entering the topic, let’s take a look at this. In advanced mathematics, we can find the area of the curved edge of a quadratic function through definite integral.

We can divide the area under the curve into n slender rectangles. When n infinity approaches infinity, the area of all rectangles is equal to the area of the curved edge figure.

Two simple diagrams, the picture is taken from Why can the definite integral find the area? :

When n infinity approaches infinity, the area of all rectangles is equal to the area of the curved edge figure:

image

Using this idea, we can also simulate a curved edge in CSS through multiple divs, which is a wavy line.

Step 1. Cut the graph into multiple copies

First, we can define a parent container with 12 child divs under the parent container:

<div class="g-container">
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
</div>

Through the flex , a simple layout, to get such a graphic, each sub-element has the same height:

.g-container {
    width: 200px;
    height: 200px;
    border: 2px solid #fff;
    display: flex;
    align-items: flex-end;
}

.g-item {
    flex-grow: 1;
    height: 60px;
    background-color: #fff;
}

The effect is as follows:

Step 2. Let each child element run the height transformation animation with a different negative delay

Next, with a simple transformation, we need to make this graph move by changing the height of each child element:

.g-item {
    flex-grow: 1;
    height: 60px;
    background-color: #000;
    animation: heightChange 1s infinite ease-in-out alternate;
}

@keyframes heightChange {
    from {
        height: 60px;
    }
    to {
        height: 90px;
    }
}

The effect is as follows:

Next, you only need to set a different time negative delay for the animation sequence of each child element, and you can get a preliminary wave effect. Here, in order to reduce the workload, we use SASS to achieve:

$count: 12;
$speed: 1s;

.g-item {
    --f: #{$speed / -12};
    flex-grow: 1;
    height: 60px;
    background-color: #000;
    animation: heightChange $speed infinite ease-in-out alternate;
}

@for $i from 0 to $count {
    .g-item:nth-child(#{$i + 1}) {
        animation-delay: calc(var(--f) * #{$i});
    }
}

@keyframes heightChange {
    from {
        height: 60px;
    }
    to {
        height: 90px;
    }
}

In this way, we get a preliminary wave effect:

Step 3. Anti-aliasing

As you can see, the above wave animation has a certain degree of aliasing. The next thing we need to do is to eliminate these aliases as much as possible.

Method 1: Increase the number of divs

According to the idea of using definite integral to find the area of the curved edge figure at the beginning, we only need to increase the number of sub-divs as much as possible. When the number of divs is infinite, the sawtooth will disappear.

We can try to replace the 12 sub-divs mentioned above with 120. It is too laborious to write 120 divs one by one. Here we use Pug template engine:

div.g-container
 -for(var i=0; i<120; i++)
    div.g-item

For the CSS code, you only need to change the animation delay time, and the negative delay of the 120 sub-divs is controlled within 1s:

// 12 -- 120
$count: 120;
$speed: 1s;

.g-item {
    // 注意,只有这里发生了变化
    --f: #{$speed / -120};
    flex-grow: 1;
    height: 60px;
    background-color: #000;
    animation: heightChange $speed infinite ease-in-out alternate;
}

@for $i from 0 to $count {
    .g-item:nth-child(#{$i + 1}) {
        animation-delay: calc(var(--f) * #{$i});
    }
}

In this way, we can get a smoother curve:

Method 2: Simulate radians through transform: skew()

Of course, in reality, using so many divs is too wasteful, so is there any other way to eliminate aliasing as much as possible when the number of divs is relatively small?

Here, we can try to add different transform: skewY() to the child element in the process of motion transformation to simulate the arc.

Re-modify the code, we lower the number of divs, and add a transform: skewY() animation effect to each sub-div:

div.g-container
 -for(var i=0; i<24; i++)
    div.g-item

The complete CSS code is as follows:

$count: 24;
$speed: 1s;

.g-item {
    // 注意,只有这里发生了变化
    --f: #{$speed / -24};
    flex-grow: 1;
    height: 60px;
    background-color: #000;
    animation: 
        heightChange $speed infinite ease-in-out alternate,
        skewChange $speed infinite ease-in-out alternate;
}

@for $i from 0 to $count {
    .g-item:nth-child(#{$i + 1}) {
        animation-delay: 
            calc(var(--f) * #{$i}), 
            calc(var(--f) * #{$i} - #{$speed / 2});
    }
}

@keyframes heightChange {
    from {
        height: var(--h);
    }
    to {
        height: calc(var(--h) + 30px);
    }
}

@keyframes skewChange {
    from {
        transform: skewY(20deg);
    }
    to {
        transform: skewY(-20deg);
    }
}

To facilitate understanding, let’s first take a look at how the transformation of skewY()

It can be seen that each transformation has obvious jagged protrusions. Superimposed on the delayed height transformation, most of the jagged effects can be eliminated very well:

At this point, we have another anti-aliasing method with a moderate number of divs! The complete code for all the above effects, you can click here:

CodePen -- PureCSS Wave Effects

Mixed use

Finally, we can combine several different wave effects by adjusting several variable parameters to get some combined effects, which is also very good.

Something like this:

CodePen -- PureCSS Wave Effects 2

Based on this, I think of the LOGO of Sea Group, the parent company of our company (Shopee), which looks like this:

Use the scheme of this article to realize a dynamic LOGO animation for it:

CodePen Demo -- PureCSS Wave - Sea Group Logo

Disadvantage

The disadvantages of this scheme are still obvious:

  • The first is to waste divs. More divs are needed to achieve the effect, and the more divs, the better the effect will be. Of course, it will increase to a certain extent, and stuttering is inevitable.
  • The sawtooth cannot be completely eliminated. This is the most deadly or the place where it can really be useful.

Of course, the purpose of this article is more to open up thinking, explore the advantages and disadvantages of this method, the entire process of realizing animation, and the use of animation negative delay time, all have some reference and learning significance. CSS is still very interesting~ 🤣

At last

Okay, this concludes this article, I hope it helps you :)

If you want to get the most interesting CSS information, don’t miss my account - 160a326b5ef5e4 iCSS front-end interesting 160a326b5ef5e8 😄

More wonderful CSS technical articles are summarized in my Github - iCSS , which is continuously updated, welcome to click a star to subscribe to the collection.

If you have any questions or suggestions, you can exchange more, original articles, limited writing style, and lack of knowledge. If there are any irregularities in the article, please let me know.


chokcoco
12.3k 声望18.5k 粉丝