CSS методы для эффекта волнового материала

Руководство по различным методам создания волнового эффекта с использованием CSS и JavaScript

Недавно мне пришлось реализовать эффект пульсации от материального дизайна в веб-приложении. И тогда я понял, что понятия не имею, как это реализовано. Это привело меня в путешествие по изучению существующих реализаций и даже придумала совершенно новую технику, которая может оказаться полезной для вас.

Что это за эффект ряби?

Подождите, вы не знаете, волновой эффект от Google Material Design? Вы прожили в пещере сколько лет?

Эффект пульсации используется при нажатии кнопки. Это работает так же для мыши или сенсорного взаимодействия.

Положение, которое вы нажимаете или касаетесь кнопки, называется точкой контакта. Оттуда пульсация движется наружу, теряя непрозрачность по мере увеличения, пока не заполнит всю кнопку. Тогда он исчезает полностью.

Динамика этого волнового эффекта похожа на рябь, возникающую при прикосновении к поверхности жидкости или при падении камня в озеро.

Рябь вы найдете в Интернете

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

Использование псевдоэлемента :: after

Используя эту технику, псевдоэлемент кнопки :: after оформляется в виде полупрозрачного круга и анимируется для увеличения и уменьшения. Контейнерная кнопка должна иметь переполнение: скрытый, чтобы окружность никогда не переливалась за пределы поверхности кнопки, и положение: относительно, чтобы упростить размещение круга внутри кнопки. Вы можете прочитать более подробную информацию об этой технике в этой статье Ionuț Colceriu.

Одна из замечательных особенностей этого метода заключается в том, что это чисто CSS-решение с эффектом ряби. Тем не менее, волновой эффект всегда начинается с центра кнопки, а не с точки соприкосновения. Это не самая естественная обратная связь.

Это можно улучшить, используя JavaScript для хранения точки соприкосновения и использования его для позиционирования пульсации. Это именно то, что material.io сделал для их веб-компонента пульсации. Он использует CSS-переменные для хранения точки контакта, а псевдоэлемент :: after использует эти переменные для позиционирования.

Использование дочерних элементов

По сути, эта техника использует ту же стратегию, что и раньше. Но вместо псевдоэлемента он добавляет элемент span внутри кнопки, который затем можно позиционировать с помощью JavaScript. Эта техника описана в этой статье Jhey Tompkins.

Простейшая реализация создает интервал для каждого щелчка по кнопке и использует положение мыши на событии щелчка, чтобы изменить позицию пролета. Анимация CSS заставляет диапазон расти и исчезать до полной прозрачности Мы можем выбрать удаление промежутка из DOM, как только анимация закончится, или просто оставить его там под ковром - никто не заметит, что вокруг висит прозрачный промежуток.

Я нашел другой вариант этого, в котором дочерним элементом является svg вместо span, а svg анимируется с помощью JavaScript. Это изменение объясняется Деннисом Гебелем, но в сущности оно кажется тем же и, возможно, позволяет использовать сложные формы и эффекты SVG.

Проблема с отправкой входных данных

Оба метода, описанные выше, кажутся великолепными. Но это то, что происходит, когда я пытался применить их к элементам ввода с type = submit:

Почему они не работают?

Элемент ввода является заменяемым элементом. Короче говоря, это означает, что вы мало что можете сделать с этими элементами в отношении DOM и CSS. В частности, они не могут иметь дочерних элементов и псевдоэлементов. Теперь понятно, почему эти методы не работают.

Поэтому, если вы используете Material Design, лучше держаться подальше от ввода [type = submit] и придерживаться элементов кнопки. Или просто продолжайте читать.

Добавление пульсаций для отправки входных данных

В веб-приложении, над которым я работал, у нас уже было много кнопок отправки. Изменение всех их, чтобы стать другим элементом, потребовало бы большой работы и высокого риска взлома таблиц стилей и логики JavaScript. Поэтому мне пришлось выяснить, как добавить рябь к существующим кнопкам отправки.

Использование упаковочного контейнера

Я быстро понял, что могу обернуть кнопку отправки внутри элемента встроенного блока и использовать элемент встроенного блока в качестве поверхности пульсации. Вот короткая демонстрация:

Хотя мне и нравится это решение за его простоту, оно все равно требовало от меня разметки в слишком многих местах И я знал, что это будет хрупкое решение - новые разработчики зайдут в проект и создадут кнопки отправки, не оборачивая их должным образом в рябь. Поэтому я продолжал искать другие решения, не требующие смены DOM.

Радиальные градиенты

Синтаксис радиального градиента позволяет мне контролировать как центр, так и размер градиента. Конечно, это также позволяет мне контролировать цвет градиента, включая полупрозрачные цвета. И он никогда не переполняет элемент, к которому он применяется. Похоже, он уже делает все, что мне нужно!

Не так быстро ... отсутствует одна вещь: свойство background-image не анимируемо. Я не мог заставить градиент расти и переходить в прозрачный с помощью CSS-анимации. Мне удалось заставить его расти, анимируя свойство background-size, но это было все, что я мог сделать.

Я попробовал несколько других вещей, таких как наличие замирающего круга в качестве анимированного изображения (используя формат apng), и применил его в качестве фонового изображения. Но тогда я не мог контролировать, когда цикл изображения начинается и заканчивается.

Наконец, решение с помощью JavaScript

Что вы не можете сделать в CSS, вы можете сделать это в JavaScript. Потратив больше времени, чем я готов признать, пытаясь заставить этот эффект работать с использованием CSS-анимации, я просто сдался и решил написать анимацию на JavaScript.

Я начал с решения для радиального градиента выше и использовал window.requestAnimationFrame для плавной анимации радиального градиента, растущего и исчезающего. Вот мое окончательное решение:

Заключение

Таким образом, можно использовать волновые эффекты для кнопок отправки, но не только с помощью CSS.

Я не мог найти эту технику, документированную где-либо в сети, поэтому я называю ее своей. Техника пульсации Леонардо не требует изменений в DOM и работает для любого элемента, потому что она не опирается на псевдоэлементы или дочерние элементы. Тем не менее, это не безупречное решение.

Во-первых, есть производительность. Анимируя градиент с помощью JavaScript, вы теряете много оптимизаций браузера. Но поскольку изменяемое единственное свойство - это background-image, я подозреваю, что браузерам не нужно будет перекомпоновывать, а просто потребуется повторно применить стили и перерисовать элемент. На практике это именно то, что происходит, и производительность действительно хорошая. Исключением из этого утверждения является Firefox Mobile, который по некоторым причинам не поспевает за анимацией. (редактировать: анимация плавная в современных версиях Firefox Mobile)

Во-вторых, техника использует свойство background-image кнопки. Если ваш дизайн требует, чтобы к кнопкам было применено изображение к фону, эффект ряби переопределит это. Если вам действительно нужно это изображение в дизайне, тогда JavaScript можно изменить, чтобы нарисовать радиальный градиент поверх существующего фонового изображения.

В-третьих, это не похоже на работу в Internet Explorer. Однако я не вижу причин, по которым он не должен работать с IE10 и выше. Возможно, это потому, что IE использует другой синтаксис для радиального градиента. Но кого волнует IE сегодня? (редактировать: этот метод работает без проблем в Internet Explorer 11)