5
头图

Recently, the S11 LPL Spring Split started. In the process of watching the game, I found that a new and interesting masking effect appeared in the Ban/Pick selection stage of the new season, as shown in the following figure:

Of course, it is a dynamic effect. In the process of electing people, there will be a breathing effect:

The Gif image is a bit blurry, in general, it is a masking effect close to fog. And, he can change dynamically.

This article will explore how we can achieve a similar effect in CSS.

To achieve a smoke mask effect

First, let's try to implement such a dynamic mask:

Assuming there are no blurred edges and smoke effects, it's actually a gradient:

<div></div>
div {
    width: 340px;
    height: 180px;
    border: 2px solid #5b595b;
    background: linear-gradient(
        rgba(229, 23, 49, 1),
        rgba(229, 23, 49, .9) 48%,
        transparent 55%,
    );
}

Through the above code, we can get:

Well, it looks really unremarkable, how can we use it to get a foggy effect?

When it comes to smoke, smart students should be able to think of filters. Of course, it is the <feturbulence> filter of SVG.

That's right, it's it again, <feturbulence> is really interesting, my last two articles about it -- Amazing! ! Can CSS also achieve smoke effect? , Amazing! ! Can CSS also achieve aurora? can be read together.

<feturbulence> of type="fractalNoise" for simulating cloud and fog effects. This filter uses the Perlin noise function to create an image that enables a semi-transparent smoked or wavy image for some special textures.

Here, we use the <feturbulence> filter to simply process the above graph:

<div></div>

<svg width="0">
  <filter id="filter">
    <feTurbulence id="turbulence" type="fractalNoise" baseFrequency=".03" numOctaves="20" />
    <feDisplacementMap in="SourceGraphic" scale="30" />
  </filter>
</svg>

In CSS, you can use filter: url() to introduce this filter to the corresponding element:

div {
    ...
    filter: url(#smoke);
}

The effect of the element with the filter applied:

Since I added a border to the element, the entire border is also fogged. This is not what we want. We can use pseudo-elements to transform them. border is applied to the container, the pseudo-element is used to achieve gradient, and the filter is applied to the pseudo-element :

div {
    position: relative;
    width: 340px;
    height: 180px;
    border: 2px solid #5b595b;
    
    &::before {
        content: "";
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        background: linear-gradient(
            30deg,
            rgba(229, 23, 49, 1),
            rgba(229, 23, 49, .9) 48%,
            transparent 55%,
        );
        filter: url(#smoke);
    }
}

The effect after transformation is as follows:

Ok, one step closer, but there are a lot of imperfections around that are not filled. It's not a big problem, let's change the positioning top \ left \ right \ bottom , let the pseudo element exceed the parent container, the parent container can be set to overflow: hidden :

div {
    ....
    overflow: hidden;
    
    &::before {
        ....
        left: -20px;
        top: -10px;
        right: -20px;
        bottom: -20px;
        background: linear-gradient(
            30deg,
            rgba(229, 23, 49, 1),
            rgba(229, 23, 49, .9) 48%,
            transparent 55%,
        );
        filter: url(#smoke);
    }
}

After adjustment, take a look at the effect:

It feels a bit like that. Next, we only need to make the smoke element move. In order to make the whole effect coherent (because SVG animation itself does not support such features as animation-fill-mode: alternate ), we still need to write a little JavaScript code to control the overall loop of the animation.

The approximate code is this:

const filter = document.querySelector("#turbulence");
let frames = 1;
let rad = Math.PI / 180;
let bfx, bfy;

function freqAnimation() {
    frames += .35;

    bfx = 0.035;
    bfy = 0.015;

    bfx += 0.006 * Math.cos(frames * rad);
    bfy += 0.004 * Math.sin(frames * rad);

    bf = bfx.toString() + " " + bfy.toString();
    filter.setAttributeNS(null, "baseFrequency", bf);

    window.requestAnimationFrame(freqAnimation);
}

window.requestAnimationFrame(freqAnimation);

In fact, there is only one thing this code does, which is to make the baseFrequency attribute of the #turbulence filter of SVG loop infinitely in an interval, that's all. Make the whole smoke constantly changing by changing baseFrequency .

So far, we have got a complete, moving smoke mask:

Add the pictures in the box below to get the effect of the renderings given at the beginning:

The complete code, you can click here -- CodePen Demos -- LPL BAN PICK MASK Effect

Realize the mask effect of breathing state

On the basis of the above, adding the effect of breathing is actually very simple.

We only need to change one position of the gradient. There are many methods. Here I will give a more elegant method but the compatibility may not be so good - CSS @property.

Simple modification of the above code:

@property --per {
    syntax: "<percentage>";
    inherits: false;
    initial-value: 22%;
}
div::before {
    ...
    background: linear-gradient(
        30deg,
        #ff0020,
        rgba(229, 23, 49, .9) var(--per),
        transparent calc(var(--per) + 8%),
    );
    filter: url(#smoke);
    animation: change 2s infinite ease-out;
}
@keyframes change {
    50% {
        --per: 18%;
    }
}

In this way, the breathing effect is achieved:

For the complete code, you can click here -- CodePen Demos -- LPL BAN PICK MASK Effect

At last

Well, this is the end of this article, I hope this article will help you :)

If you want to get the most interesting CSS information, don't miss my official account -- iCSS front-end anecdote 😄

More wonderful CSS technical articles are summarized in my Github -- iCSS , which will be updated continuously. Welcome to click star to subscribe to the collection.

If you have any questions or suggestions, you can communicate more. Original articles are limited in writing and knowledge. If there are any inaccuracies in the article, please let me know.


chokcoco
12.2k 声望18.5k 粉丝