Недавно я увидел очень интересный эффект на 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); } }
здесь:
- Мы используем случайную функцию SASS
$width: random(100) + px;
для случайного создания кругов div разных размеров. - Использование случайной функции SASS
left: #{(random(100)) + '%'}
,top: #{(random(100))}px
случайного позиционирования на основе родительского элемента - Ядром является
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-фильтров и детали, о которых вы не знаете
Кратко опишите эту технику:
Выньте два фильтра отдельно, и их функции:
filter: blur()
: Установите эффект размытия по Гауссу на изображении.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.