Сегодня мы хотим показать вам как создать интригующе простой, но привлекательный эффект перехода с помощью CSS свойства mask. Вы узнаете как применить новые свойства для современного эффекта перехода на простом слайд-шоу.
Обратите внимание, что этот эффект - экспериментальный и поддерживается далеко не всеми браузерами:
Для проверки браузерной поддержки мы воспользуемся библиотекой Modernizr.
Создание изображения-маски
В этом уроке мы реализуем первый пример (демо-1).
Чтобы эффект перехода маски работал, нам потребуется изображение, которое мы будем использовать, чтобы скрыть/показать кое-какие части нашего основного изображения. Это изображение-маска будет представлять собой PNG с прозрачными частями. Само PNG-изображение будет спрайтовым и выглядеть так:
В то время как черные области будут показывать текущее изображение, белые (которые на самом деле прозрачные) будут замаскированной частью нашего изображения, который покажет второе изображение. Для того, чтобы создать спрайт-изображение, мы будем использовать это видео:
Мы импортируем его в Adobe After Effects, чтобы уменьшить синхронность видео, удалить белую часть и экспортируем в виде последовательности в PNG. Для того, чтобы уменьшить длительность до 1,4 секунд (длительность нашего перехода) мы будем использовать эффект Time stretch.
Для удаления белой области мы будем использовать Keying -> extract, установив белую точку на 0
. На скриншоте ниже, синяя часть - прозрачная часть на видео, фон нашей композиции.
И, наконец, мы можем сохранить нашу композицию в виде последовательности PNG, а затем использовать Photoshop или генератор CSS-спрайта для создания единого изображения:
Это изображение отлично подходит для эффекта появления. Создадим еще один, «обратный» спрайт для противоположного эффекта. Вы найдете различные спрайты в папке img в архиве с демо-файлами.
Теперь, когда мы создали изображение-маску, давайте погрузимся в HTML структуру нашего слайдера.
HTML-разметка слайдера
Для нашего демо мы создадим простое слайд-шоу, чтобы показать эффект маски. Наше слайд-шоу будет заполнять весь экран, а кроме того, мы добавим несколько стрелок, которые будут запускать слайд-переходы. Идея заключается в том, чтобы наложить слайды, а затем изменить z-index входящего слайда, когда анимация закончена. Структура нашего слайд-шоу выглядит следующим образом:
<div class="page-view">
<div class="project">
<div class="text">
<h1>“Хорошо быть <br> дикой и свободной”</h1>
<p>Фото Андреаса Роннингена</p>
</div>
</div>
<div class="project">
<div class="text">
<h1>“В дикой природе”</h1>
<p>Фото Джона Прайса</p>
</div>
</div>
<div class="project">
<div class="text">
<h1>“Весна пришла?”</h1>
<p>Фото Томаса Лефебвра</p>
</div>
</div>
<div class="project">
<div class="text">
<h1>“Любопытство”</h1>
<p>Фото Марии</p>
</div>
</div>
<nav class="arrows">
<div class="arrow previous">
<svg viewBox="208.3 352 4.2 6.4">
<polygon class="st0" points="212.1,357.3 211.5,358 208.7,355.1 211.5,352.3 212.1,353 209.9,355.1"/>
</svg>
</div>
<div class="arrow next">
<svg viewBox="208.3 352 4.2 6.4">
<polygon class="st0" points="212.1,357.3 211.5,358 208.7,355.1 211.5,352.3 212.1,353 209.9,355.1"/>
</svg>
</div>
</nav>
</div>
Блок page-view наш глобальный контейнер, он будет содержать все наши слайды. Блоки project - слайды нашего слайд-шоу; каждый из них содержит заголовок и легенду. Кроме того, мы установим индивидуальный фоновое изображение для каждого слайда. Стрелки служат переключателем для следующей или предыдущей анимации, а также служат для перемещения по слайдам. Давайте посмотрим на CSS стили для слейдера.
CSS стили для слайдера
В этой части мы поработаем над CSS для нашего эффекта. Также мы создадим макет классического полноэкранного слайдера, с отцентрированными названиями и навигацией в левой нижней части страницы. Кроме того, напишем несколько медиазапросов, чтобы адаптировать слайдер для мобильных устройств.
Далее, настроим наши спрайтовые изображения так, чтобы они были невидимым фоном и загружались при открытии страницы.
.demo-1 {
background: url("/img/nature-sprite.png") no-repeat -9999px -9999px;
background-size: 0;
}
.demo-1 .page-view {
background: url(/img/nature-sprite-2.png) no-repeat -9999px -9999px;
background-size: 0;
}
Каждый слайд будет иметь различное фоновое изображение:
.demo-1 .page-view .project:nth-child(1) {
background-image: url("/img/nature-1.jpg");
}
...
.demo-1 .page-view .project:nth-child(4) {
background-image: url("/img/nature-4.jpg");
}
Это та вещь, которую хочется сделать динамичной, но нам важен сам эффект, поэтому не будем ничего здесь усложнять.
Определим класс с именем hide, который будем добавлять к слайду всякий раз, когда мы хотим скрыть его.
Зная, что кадр составляет 100% от экрана, а наша анимация содержит 23 изображения, - установим ширину в 23 * 100% = 2300%.
Теперь добавим CSS анимацию с использованием steps. Мы хотим, чтобы наш спрайт останавливался в начале последнего кадра. Следовательно, для достижения этой цели, мы должны задействовать на один шаг меньше, т.е. будет 22 шага:
.demo-1 .page-view .project:nth-child(even).hide {
-webkit-mask: url("/img/nature-sprite.png");
mask: url("/img/nature-sprite.png");
-webkit-mask-size: 2300% 100%;
mask-size: 2300% 100%;
-webkit-animation: mask-play 1.4s steps(22) forwards;
animation: mask-play 1.4s steps(22) forwards;
}
.demo-1 .page-view .project:nth-child(odd).hide {
-webkit-mask: url("/img/nature-sprite-2.png");
mask: url("/img/nature-sprite-2.png");
-webkit-mask-size: 7100% 100%;
mask-size: 7100% 100%;
-webkit-animation: mask-play 1.4s steps(70) forwards;
animation: mask-play 1.4s steps(70) forwards;
}
Наконец, мы определяем ключевые кадры анимации:
@-webkit-keyframes mask-play {
from {
-webkit-mask-position: 0% 0;
mask-position: 0% 0;
}
to {
-webkit-mask-position: 100% 0;
mask-position: 100% 0;
}
}
@keyframes mask-play {
from {
-webkit-mask-position: 0% 0;
mask-position: 0% 0;
}
to {
-webkit-mask-position: 100% 0;
mask-position: 100% 0;
}
}
Наш слайдер структурирован и стилизован. Давайте теперь превратим его в нечто функциональное!
JavaScript для слайдера
Воспользуемся для демонстрации библиотекой zepto.js, которая представляет собой JavaScript-фреймворк, похожий на JQuery.
Мы начнем с объявления всех наших переменных, установим продолжительность и элементы. Затем инициализируем события, получим текущий и следующий слайд, установим правильный z-index.
function Slider() {
// Продолжительность
this.durations = {auto: 5000, slide: 1400};
// DOM
this.dom = {
wrapper: null,
container: null,
project: null,
current: null,
next: null,
arrow: null
};
// Прочие настройки
this.length = 0;
this.current = 0;
this.next = 0;
this.isAuto = true;
this.working = false;
this.dom.wrapper = $('.page-view');
this.dom.project = this.dom.wrapper.find('.project');
this.dom.arrow = this.dom.wrapper.find('.arrow');
this.length = this.dom.project.length;
this.init();
this.events();
this.auto = setInterval(this.updateNext.bind(this), this.durations.auto);
}
/* Установить начальный z-index и получить текущий проект */
Slider.prototype.init = function () {
this.dom.project.css('z-index', 10);
this.dom.current = $(this.dom.project[this.current]);
this.dom.next = $(this.dom.project[this.current + 1]);
this.dom.current.css('z-index', 30);
this.dom.next.css('z-index', 20);
};
Мы отслеживаем нажатие на стрелки, если же слайд-шоу в настоящее время не участвует в анимации, мы проверяем был ли клик на стрелке следующий/предыдущий слайд. Также мы изменяем значение переменной next
и переходим к изменению слайда.
/* Инициализируем события */
Slider.prototype.events = function () {
var self = this;
this.dom.arrow.on('click', function () {
if (self.working) return;
self.processBtn($(this));
});
};
Slider.prototype.processBtn = function (btn) {
if (this.isAuto) {
this.isAuto = false;
clearInterval(this.auto);
}
if (btn.hasClass('next'))
this.updateNext();
if (btn.hasClass('previous'))
this.updatePrevious();
};
/* Обновляем следующий глобальный индекс */
Slider.prototype.updateNext = function () {
this.next = (this.current + 1) % this.length;
this.process();
};
/* Обновляем предыдущий глобальный индекс */
Slider.prototype.updatePrevious = function () {
this.next--;
if (this.next < 0)
this.next = this.length - 1;
this.process();
};
Эта функция является сердцем нашего слайд-шоу: мы устанавливаем класс hide к текущему слайду, и как только анимация закончится, мы уменьшаем z-index предыдущего слайда, увеличиваем его на текущем слайде, а затем удаляем класс hide предыдущего слайда.
/* Расчет и переключение между слайдами */
Slider.prototype.process = function () {
var self = this;
this.working = true;
this.dom.next = $(this.dom.project[this.next]);
this.dom.current.css('z-index', 30);
self.dom.next.css('z-index', 20);
// скрываем текущий слайд
this.dom.current.addClass('hide');
setTimeout(function () {
self.dom.current.css('z-index', 10);
self.dom.next.css('z-index', 30);
self.dom.current.removeClass('hide');
self.dom.current = self.dom.next;
self.current = self.next;
self.working = false;
}, this.durations.slide);
};
Добавление соответствующих классов будет вызывать нашу анимацию, которая в свою очередь применит маску к нашим слайдам. Идея заключается в том, чтобы двигать маску по шагам, чтобы создать анимационный переход.
Вот и все! Я надеюсь, что вы нашли этот учебник полезным и получать удовольствие, создавая свои собственные интересные эффекты маски!