Оглавление

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

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

JavaScript код

Для начала напишем небольшой JS код:

// Ищем все кнопки
const buttons = document.getElementsByClassName('btn');
for (let i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener('click', function (e) {
        // При нажатии на кнопку, внутри создаем элемент span, который и будет волной
        const wave = document.createElement('span'),
            // Получаем размеры и координаты элемента в месте клика относительно viewport
            waveOffset = this.getBoundingClientRect();

        // Вычисляем координаты вычитанием координат элемента из координат документа
        const waveY = e.pageY - waveOffset.top,
            waveX = e.pageX - waveOffset.left;

        // Полученные координаты записываем в стили тегу span
        wave.style.top = waveY + 'px',
            wave.style.left = waveX + 'px',
            wave.style.background = this.getAttribute('data-button-background');

        // Внутри кнопки по клику создаем span с координатами, которые формируются в зависимости от того, куда кликнем
        this.appendChild(wave);

        // Удаляем созданный тег span после 1.5 секунд
        setTimeout(function () {
            wave.parentNode.removeChild(wave);
        }, 1500);
    });
}

Как и всегда, я проставил много комментариев. Но если тезисно — данный код находит все кнопки по классу .btn, далее при клике внутри кнопки создается элемент span, который будет создавать тот самый эффект волн как в Material Design / Materialize фреймворке.

При клике на элемент, скрипт вычисляет его координаты, вычитает их из координат документа (не путать с координатами браузера) и полученные координаты заносит в инлайновые стили top и left. Некая динамическая генерация волн.

Прописываем CSS стили

Динамическое определение волн есть. Но их еще нужно анимировать. Напишем несколько стилей и анимацию с помощью кейфреймов:

.btn {
    position: relative;
    overflow: hidden;
    z-index: 1;
}

.btn span {
    position: absolute;
    height: 12px;
    width: 12px;
    border-radius: 100%;
    background: #FFFFFF;
    animation: buttonWave 1.6s;
}

@keyframes buttonWave {
    0% {
        opacity: 0.2;
        transform: scale(1);
    }
    100% {
        opacity: 0;
        transform: scale(40);
    }
}

Анимацию волн можно регулировать в @keyframes buttonWave.

В одном из решений в интернете подсмотрел возможность задавать цвет волн с помощью дата атрибута:

<button class="btn btn-default" data-button-background="#323479">Button 1</button>
<button class="btn btn-default" data-button-background="#cb2e77">Button 2</button>
<button class="btn btn-default">Button 3</button>

Прозрачность цвета волн регулируется в @keyframes buttonWave, через параметр opacity. Но этот дата-атрибут можно просто не заполнять, скрипт ругаться не будет.

Результат и исходники