[Перевод] Липкий эффект
Буквально недавно Крис написал про «Эффект капельного преобразования в CSS». Эффект реально крутой и сама техника реализована по-умному, но данный подход через обычные CSS фильтры имеет определенные недостатки: нельзя использовать непрозрачность, добавлять контент внутрь капель, проблемы с фоновыми цветами.В последние дни я достаточно много экспериментировал с SVG фильтрами и заметил, что с их помощью можно решить вышеописанные проблемы в CSS реализации. Посмотрите на липкое меню, которое я сделал для демонстрации:
CodePen
SVG Filters 101SVG фильтры — это очень мощная штука. Но это очень обширная тема, поэтому мы поговорим только о самом необходимом для решения нашей задачи.Несмотря на название мы можем применять эти фильтры к DOM элементам с помощью CSS и это будет работать в большинстве браузеров.
Классический синтекс для описания фильтров:
Применение фильтра к DOM элементу:
.selector { filter: url ('#name-of-your-filter-here');
/* you can also load filters from external SVGs this way: */ filter: url ('filters.svg#name-of-your-other-filter-here'); } Вам могут понадобиться вендорные префиксы для свойства filter.
Элемент содержит в себе от одного и более фильтровых приметив (filter primitives), которые выполняют функции blur, color transform, shading. Полные перечень этих примитив находится тут.
Взглянем на парочку примеров:
CodePen
Давайте рассмотрим пример немного посложнее: drop shadow. В нем наглядно показано как работает цепочка фильтровых приметив вместе:
CodePen
Обратите внимание на приметиву
Теперь, когда мы понимает базовые принципы работы SVG фильтров, давайте разберемся как делать липкий эффект.
Закрепим уже пройденное Основная техника описана здесь. Напомню, что идея заключается в том, чтобы одновременно размывать и контрастировать элементы. И все заработает магическим образом.CodePenОднако, мы по прежнему имеем:
Проблемы в работе с разным цветами. Размытие производится для всего элемента, включая содержимое. Невозможность использовать непрозрачность. Все это не позволяет применить данный трюк в реальном проекте.
С помощью SVG фильтров мы можем реализовать то, что не было возможно с CSS: мы можем увеличивать контрастность только для альфа-канала, не изменяя цвета; и с помощью SourceGraphic мы можем применять размытие только для самого элемента, не меняя содержимое.Также поскольку мы работаем с альфа-каналом, то не только он должен быть прозрачным, прозрачный фон необходим, будьте осторожны с этим.
Основной код:
Во-первых мы произвели размытие в 10 пикселей и присвоим имя данному результату. Затем для получившегося результата мы применили color matrix filter для увеличения контрастности альфа-канала. И после этого мы вставили оригинальным графический объект в этот эффект. О Color Matrices Если вы до этого не использовали color matrix filter, то тогда необходимо пояснить как это работает. Представьте таблицу из четырех строк и пяти столбцов. Она будет выглядеть следующим образом. | R | G | B | A | + ---|------------------- R | 1×0 | 0×0 | 0 ---|------------------- G | 0×1 | 0×0 | 0 ---|------------------- B | 0×0 | 1×0 | 0 ---|------------------- A | 0×0 | 0×1 | 0 ---|------------------- Каждая строка представляет из себя канал (red, green, blue и alpha) и использует для установки значения канала. Первые четыре столбца также представляют из себя каналы. Число в клетке являет мультипликатором канала в столбце для канала в строке. Например, 0.5 в строке R и столбце G добавит к красному каналу текущее значение Green*0.5. Последняя колонка уже не представляет из себя канал и используется для добавления или вычитания. Числа указанные в ней умножаются на 255 и присваиваются соответствующему каналу.
Это долго объяснять, но на самом деле использование фильтра предельно простое. В нашем случае мы изменяем только значение альфа-канала и наша матрица будет выглядеть так:
| R | G | B | A | + ---|------------------- R | 1×0 | 0×0 | 0 ---|------------------- G | 0×1 | 0×0 | 0 ---|------------------- B | 0×0 | 1×0 | 0 ---|------------------- A | 0×0 | 0×18 |-7 ---|------------------- RGB каналы остаются неизмененными. Значение альфа-канала умножается 18, а затем из него вычитается 7×255, эффективно увеличивая контраст одной только прозрачности. Все значения можно настроить под ваши потребности.
Чтобы применить эту матрицу для feColorMatrix фильтра, мы должны написать все значения в определенном порядке:
values=»1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7» Демо В итоге задуманный нами эффект работает. Пример: CodePen
Вы можете кастомизировать все, что вам нужно, добавить тень, изменить цвет каждого элемента, все в вашем распоряжении!
Подытожим
Фильтр должен применять к контейнеру с элементами, а не к самим элементам.
Из за самого тянущего эффекта контейнер должен быть немного большей области чем содержимое. В противном случае вы можете получить подобные дефекты на краях:
Для того, чтобы применять данный фильтр к примеру для прямоугольников мы должны воспользоваться немного более изощренным способом. Вместо отрисовки оригинального объекта над липкоим эффектом, мы должны применить feComposite фильтр с атрибутом atop, для того чтобы скрыть все, что выходит за рамки: