Недавно я увидел очень интересный эффект на CodePen:

Основная сложность этого эффекта заключается в особом эффекте слияния пузырьков.

Исходный код находится по адресу: CodePen Demo — Goey footer, автор в основном использует фильтр SVG для завершения эффекта. Если вам интересно, вы можете проверить исходный код.

Среди них, чтобы гибко использовать фильтры в SVG feGaussianBlur фильтрам по-прежнему нужен очень сильный запас знаний SVG. Итак, можно ли добиться такого эффекта только с помощью CSS?

Эй, сильный CSS, безусловно, возможен. В этой статье я шаг за шагом покажу вам, как использовать чистый CSS для достижения вышеуказанных эффектов.

Завершите грубый эффект с помощью SASS

Прежде всего, если вышеуказанный эффект не имеет эффекта слияния пузырьков, это может быть просто так:

Сделать такой эффект относительно просто, но кода будет больше, можно использовать препроцессор SASS.

Предположим, у нас есть следующая структура HTML:

<div class="g-wrap">
  <div class="g-footer">
    <div class="g-bubble"></div>
    <div class="g-bubble"></div>
    // ... 200 个 g-bubble
  </div>
</div>

Основная вещь, которую нужно сделать, это заставить 200 .g-bubble случайным образом выполнять восходящую анимацию снизу.

Здесь нам нужно использовать метод, который мы представили в этой статье CSS-анимация в простых терминахиспользование анимации-длительности и анимации-задержки для создания случайных эффектов .

Создавайте случайные эффекты с продолжительностью анимации и задержкой анимации.

Для одной и той же анимации мы используем случайное в определенном диапазоне animation-duration и случайное в определенном диапазоне animation-delay , что может эффективно создать более случайный эффект анимации и сделать анимацию более естественной.

Давайте смоделируем, если мы используем 10 кругов, которые согласуются с animation-duration и animation-delay, основной псевдокод:

<ul>
    <li></li>
    <!-- all ten lis...--> 
    <li></li>
</ul>
ul {
    display: flex;
    flex-wrap: nowrap;
    gap: 5px;
}
li {
    background: #000;
    animation: move 3s infinite 1s linear;
}
@keyframes move {
    0% {
        transform: translate(0, 0);
    }
    100% {
        transform: translate(0, -100px);
    }
}

Таким образом, движение мяча будет равномерным:

Чтобы движение мяча выглядело очень случайным, вам нужно только сделать так, чтобы animation-duration и animation-delay плавали в определенном диапазоне, и изменить CSS:

@for $i from 1 to 11 {
    li:nth-child(#{$i}) {
        animation-duration: #{random(2000)/1000 + 2}s;
        animation-delay: #{random(1000)/1000 + 1}s;
    }
}

Мы используем цикл SASS и функцию random(), пусть animation-duration будет случайным в диапазоне 2-4 секунд, пусть animation-delay будет случайным в диапазоне 1-2 секунд, так что мы можем получить очень естественные и разные эффекты анимации подъема, в основном нет повторяющиеся картинки и хорошая имитация случайных эффектов:

CodePen Demo — Эффект случайной анимации со случайной длительностью анимации и задержкой анимации

Что ж, давайте применим вышеупомянутые методы к эффекту, которого мы хотим достичь в этой статье. Давайте еще раз взглянем на структуру HTML:

<div class="g-wrap">
  <div class="g-footer">
    <div class="g-bubble"></div>
    <div class="g-bubble"></div>
    // ... 200 个 g-bubble
  </div>
</div>

Основной код CSS:

.g-footer {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 86px;
    width: 100%;
    background: #26b4f5;
}
@for $i from 0 through 200 { 
    .g-bubble:nth-child(#{$i}) {
        position: absolute;
        background: #26b4f5;
        $width: random(100) + px;
        left: #{(random(100)) + '%'};
        top: #{(random(100))}px;
        width: $width;
        height: $width;
        animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite;
    }
}
@keyframes moveToTop {
    90% {
        opacity: 1;
    }
    100% {
        opacity: .08;
        transform: translate(-50%, -180px) scale(.3);
    }
}

здесь:

  1. Мы используем случайную функцию SASS $width: random(100) + px; для случайного создания кругов div разных размеров.
  2. Использование случайной функции SASS left: #{(random(100)) + '%'} , top: #{(random(100))}px случайного позиционирования на основе родительского элемента
  3. Ядром является animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite , так что движение всех кругов div является случайным

Приведенные выше исчерпывающие результаты (1) и (2) создадут такой макет, равномерно распределенные круги:

Примечание. Для удобства понимания я скрыл цвет самого внешнего слоя g-footer и добавил черную рамку к g-bubble

Далее, если мы заменим оператор animation, используем единую продолжительность анимации, удалим отрицательную задержку и станем animation: moveToTop 4s ease-in-out infinite, анимация будет выглядеть так:

Все аккуратно и однородно, нет ощущения беспорядка.

Используя случайный эффект animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite , вы можете получить описанное выше ощущение, что разные пузыри поднимаются случайным образом:

Добавьте эффект слияния

Следующий, и самый важный шаг, как создать эффект слияния между пузырьками и пузырьками, а также между пузырьками и дном .g-footer ?

Этот метод часто упоминался во многих предыдущих статьях, а именно использование фильтров filter: contrast() и filter: blur().

Если вы не знаете этого трюка, вы можете ткнуть мою статью, чтобы увидеть: Трюки CSS-фильтров и детали, о которых вы не знаете

Кратко опишите эту технику:

Выньте два фильтра отдельно, и их функции:

  1. filter: blur() : Установите эффект размытия по Гауссу на изображении.
  2. filter: contrast() : Настройка контрастности изображения.

Однако, когда они «подходят», происходит чудесное явление слияния.

Посмотрите внимательно на процесс пересечения двух кругов. Когда край соприкасается с краем, возникает эффект слияния границ. Размытый край размытия по Гауссу устраняется с помощью контрастного фильтра, а размытие по Гауссу используется для достижения эффекта слияния.

Исходя из этого, мы просто трансформируем наш CSS-код, и объем кода, который необходимо добавить, очень мал:

.g-wrap {
    background: #fff;
    filter: contrast(8);
}
.g-footer {
    // ... 其他保持一致
    filter: blur(5px);
}

Это очень просто: добавьте белый цвет фона и контрастный фильтр к родительскому контейнеру filter: contrast(8) и добавьте дочерний контейнер filter: blur(5px). Таким образом, мы можем получить эффект слияния пузырей, в основном получая то, что мы хотим. Желаемый эффект:

Используйте фоновый фильтр вместо фильтра, чтобы удалить края

но! Есть небольшая проблема с использованием filter: blur() .

При использовании элемента filter: blur() недостаточно размытия края элемента, что приведет к искажению эффекта на краю. Давайте внимательнее посмотрим на край анимации:

Как это решить? С этим легко справиться. Здесь мы пытаемся использовать backdrop-filter вместо filter.

Разница между ними заключается в том, что filter действует на сам элемент, а backdrop-filter действует на все элементы, находящиеся в области позади элемента. сходства и различия между фильтром и фоновым фильтром».

Просто преобразуйте код, исходный код:

.g-footer {
    // ... 
    filter: blur(5px);
}

Модифицированный код:

.g-footer {
    // ... 去掉 filter: blur(5px)
    &:before {
        content: "";
        position: absolute;
        top: -300px;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1;
        backdrop-filter: blur(5px);
    }
}

Мы делаем это, переходя к .g-footer filter: blur(5px) через его псевдоэлемент, накладывая новый элемент поверх себя и добавляя альтернативный backdrop-filter: blur(5px).

Конечно, потому что blur(5px) также должен обслуживать слияние между пузырьками, поэтому, чтобы охватить всю область анимации, мы также установили top: -300px, чтобы расширить сферу его действия.

В итоге мы можем прекрасно воспроизвести эффект, достигнутый фильтром SVG в начале статьи:

В статье я опустил большую часть базового кода CSS, полный код вы можете нажать здесь: CodePen Demo — Bubble Rises

Окончательно

Что ж, в этой статье я представляю анимацию Motion Path и использую ее для достижения некоторых эффектов анимации пути, которые раньше было сложно реализовать. Я надеюсь, что это будет полезно для вас :)

Более интересные технические статьи по CSS собраны в моем Github — iCSS.