В последнее время мы экспериментировали с анимацией SVG. Сегодняшний урок показывает вам, как анимировать сразу несколько путей SVG, чтобы создать стильный фоновый эффект для модального окна.
Создание структуры
Структура HTML состоит из двух основных элементов: <section>
, используемого для обертывания кнопки действия #modal-trigger
и div.cd-modal
модального окна, содержащего модальный контент .cd-modal-content
и div.cd-svg-bg
, используемые для создания эффекта покрытия фона.
<main class="cd-main-content">
<section class="center">
<h1>SVG Modal Window</h1>
<a href="#0" class="cd-btn" id="modal-trigger" data-type="cd-modal-trigger">Fire Modal Window</a>
</section>
</main> <!-- .cd-main-content -->
<div class="cd-modal" data-modal="modal-trigger">
<div class="cd-svg-bg" data-step1="M-59.9,540.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L864.8-41c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3L-59.5,540.6 C-59.6,540.7-59.8,540.7-59.9,540.5z" data-step2="M33.8,690l-188.2-300.3c-0.1-0.1,0-0.3,0.1-0.3l925.4-579.8c0.1-0.1,0.3,0,0.3,0.1L959.6,110c0.1,0.1,0,0.3-0.1,0.3 L34.1,690.1C34,690.2,33.9,690.1,33.8,690z" data-step3="M-465.1,287.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L459.5-294c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3 l-925.4,579.8C-464.9,287.7-465,287.7-465.1,287.5z" data-step4="M-329.3,504.3l-272.5-435c-0.1-0.1,0-0.3,0.1-0.3l925.4-579.8c0.1-0.1,0.3,0,0.3,0.1l272.5,435c0.1,0.1,0,0.3-0.1,0.3 l-925.4,579.8C-329,504.5-329.2,504.5-329.3,504.3z" data-step5="M341.1,797.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L1265.8,216c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3L341.5,797.6 C341.4,797.7,341.2,797.7,341.1,797.5z" data-step6="M476.4,1013.4L205,580.3c-0.1-0.1,0-0.3,0.1-0.3L1130.5,0.2c0.1-0.1,0.3,0,0.3,0.1l271.4,433.1c0.1,0.1,0,0.3-0.1,0.3 l-925.4,579.8C476.6,1013.6,476.5,1013.5,476.4,1013.4z">
<svg height="100%" width="100%" preserveAspectRatio="none" viewBox="0 0 800 500">
<title>SVG Modal background</title>
<path id="cd-changing-path-1" d="M-59.9,540.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L864.8-41c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3L-59.5,540.6 C-59.6,540.7-59.8,540.7-59.9,540.5z"/>
<path id="cd-changing-path-2" d="M-465.1,287.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L459.5-294c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3 l-925.4,579.8C-464.9,287.7-465,287.7-465.1,287.5z"/>
<path id="cd-changing-path-3" d="M341.1,797.5l-0.9-1.4c-0.1-0.1,0-0.3,0.1-0.3L1265.8,216c0.1-0.1,0.3,0,0.3,0.1l0.9,1.4c0.1,0.1,0,0.3-0.1,0.3L341.5,797.6 C341.4,797.7,341.2,797.7,341.1,797.5z"/>
</svg>
</div>
<div class="cd-modal-content">
<!-- modal content here -->
</div> <!-- cd-modal-content -->
<a href="#0" class="modal-close">Close</a>
</div> <!-- cd-modal -->
<div class="cd-cover-layer"></div> <!-- .cd-cover-layer -->
Дополнительный слой div.cd-cover-layer
был использован для покрытия основного содержимого при запуске модального окна (оно расположено между модальным окном и основным содержимым страницы).
Добавление стиля
Окно .cd-modal
имеет, поначалу, visibility: hidden
, высота: 100% и ширина: 100% и находится в фиксированном положении. Когда пользователь нажимает на a#modal-trigger
, видимость модального окна изменяется на видимое (с использованием класса .modal-is-visible
).
.cd-modal {
position: fixed;
z-index: 2;
top: 0;
left: 0;
height: 100%;
width: 100%;
visibility: hidden;
transition: visibility 0s 0.6s;
}
.cd-modal.modal-is-visible {
visibility: visible;
transition: visibility 0s 0s;
}
Чтобы создать эффект модального покрытия фона, мы анимируем атрибут 'd'
элементов <path>
внутри div.cd-svg-bg>
svg (подробнее в разделе Обработка событий).
Наш первый подход к созданию «маскированного» текстового эффекта состоял в использовании SVG foreignObject для включения модального содержимого в элемент SVG. Таким образом, мы могли бы использовать элементы пути в качестве ссылки для вырезания текста вне анимированного фона. Однако у нас было несколько проблем, в основном связанных с совместимостью с браузерами.
Вот почему мы решили использовать этот простой трюк: когда модальное окно запущено, слой .cd-cover-layer
становится видимым, прямо под модальным фоном, и сразу же текст становится видимым. Уровень .cd-cover-layer
и текст имеют один и тот же цвет, таким образом, только текст поверх синих путей отображается во время анимации.
Более подробно: когда пользователь нажимает на a a#modal-trigger
, класс .modal-is-visible
добавляется в слой .cd-cover-layer
и .cd-modal
. Этот класс изменяет непрозрачность слоя .cd-cover-layer
от 0 до 1 и его видимость от скрытого до видимого, так что слой .cd-cover-layer
полностью охватывает основное содержимое страницы.
.cd-cover-layer {
position: fixed;
z-index: 1;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-color: #f2f2f2;
visibility: hidden;
opacity: 0;
transition: opacity 0.3s 0.3s, visibility 0s 0.6s;
}
.cd-cover-layer.modal-is-visible {
opacity: 1;
visibility: visible;
transition: opacity 0.3s 0s, visibility 0s 0s;
}
Как только завершится непрозрачность перехода .cd-cover-layer
, непрозрачность .cd-modal-content
будет установлена в 1:
.cd-modal-content {
color: #f2f2f2;
opacity: 0;
transform: translateY(50px);
transition: opacity 0.3s 0s, transform 0.3s 0s;
}
.modal-is-visible .cd-modal-content {
opacity: 1;
transform: translateY(0);
transition: opacity 0.3s 0.3s, transform 0.3s 0.3s;
}
Поскольку цвет .cd-modal-content
совпадает с цветом фона .cd-cover-layer
, единственным видимым контентом будет тот, что находится на синем фоне svg (который все еще оживляет), тогда как цвет .cd-cover-layer
не будет виден.
Обработка событий
Чтобы оживить модальный фон, мы анимировали атрибут 'd'
из трех элементов <path>
внутри svg.
Сначала мы определили два этапа нашей анимации.
После определения путей мы добавили в .cd-svg-bg
атрибут data-stepn
(по одному для каждого шага), равный атрибуту 'd'
определенного пути (чтобы легко получить его с помощью JavaScript).
Затем мы использовали метод animate()
, предоставленный Snap.svg для анимирования элемента пути.
modalTrigger.on('click', function(event){ //modalTrigger = $('a[data-type="cd-modal-trigger"]')
event.preventDefault();
$([modal.get(0), coverLayer.get(0)]).addClass('modal-is-visible'); //modal = $('.cd-modal'), coverLayer = $('.cd-cover-layer')
animateModal(pathsArray, pathSteps, duration, 'open');
});
function animateModal(paths, pathSteps, duration, animationType) {
var path1 = ( animationType == 'open' ) ? pathSteps[1] : pathSteps[0], // pathSteps[n] = $('.cd-svg-bg').data('step'+(n+1));
path2 = ( animationType == 'open' ) ? pathSteps[3] : pathSteps[2],
path3 = ( animationType == 'open' ) ? pathSteps[5] : pathSteps[4];
paths[0].animate({'d': path1}, duration, firstCustomMinaAnimation); //paths[0] = Snap('#cd-changing-path-1')
paths[1].animate({'d': path2}, duration, firstCustomMinaAnimation); //paths[1] = Snap('#cd-changing-path-2')
paths[2].animate({'d': path3}, duration, firstCustomMinaAnimation); //paths[2] = Snap('#cd-changing-path-3')
}