Оживляем наше порфтфолио Behance при помощи анимаций CSS
Russian (Pусский) translation by AlexBioJS (you can also view the original English article)
В предыдущих руководствах мы разобрались с тем, как использовать API Behance для обеспечения работы нашей собственной веб-страницы, и затем при помощи LESS мы сделали так, чтобы все это выглядело прилично. В данном руководстве мы улучшим удобство использования нашей веб-страницы для пользователей за счет добавления модального окна (* в графическом интерфейсе пользователя (GUI) - дочернее окно (child window) для взаимодействия пользователя с приложением: оно служит для получения информации от приложения или для ввода запрашиваемых данных и выбора опций; поэтому модальное окно часто называется диалоговым. Если открывается модальное окно, то возврат управления приложению может произойти только после реакции пользователя)) и некоторых анимаций CSS.
Добавление эффектов модального окна и анимаций
В наши дни на многих веб-сайтах с портфолио используется что-то типа модального окна для изображений их портфолио. В этом руководстве мы реализуем нечто подобное и для нашего веб-сайта. При нажатии пользователем по изображению с эскизом оно будет увеличиваться в масштабе, как и остальные изображения выбранного проекта, так что пользователи смогут рассмотреть все содержащиеся в нем изображения более детально.
Ниже приведены инструменты, необходимые нам для реализации вышеуказанного:
Magnific Popup
Мы воспользуемся плагином jQuery под названием Magnific Popup, разработанным Дмитрием Семеновым. Он небольшого размера, быстро работает и соответствует требованиям отзывчивого веб-дизайна – как раз то, что нам необходимо.
Animate.css
Также мы добавим анимации CSS, что поможет нам оживить наш веб-сайт. Мы воспользуемся несколькими фрагментами библиотеки Animate.css, которая предоставляет огромную коллекцию анимаций CSS3, которыми вы можете воспользоваться путем добавления определенных классов для немедленного применения анимаций.
Добавляем Magnific Popup
Давайте начнем с добавления таблицы стилей Magnific Popup в теге head.
1 |
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.1/normalize.min.css"> |
2 |
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/magnific-popup.js/0.9.9/magnific-popup.css"> |
3 |
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/foundation-icons.min.css"> |
4 |
<link href='http://fonts.googleapis.com/css?family=Cantata+One|Open+Sans:300,600' rel='stylesheet' type='text/css'> |
5 |
<link rel="stylesheet" href="css/style.css"> |
Затем мы добавим скрипты в самом низу страницы, благодаря чему у DOM (* Document Object Model – объектная модель документа) будет время загрузиться до загрузки скриптов, меняющих поведение элементов.
1 |
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> |
2 |
<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.min.js"></script> |
3 |
<script src="//cdnjs.cloudflare.com/ajax/libs/magnific-popup.js/0.9.9/jquery.magnific-popup.min.js"></script> |
Далее нам необходимо будет добавить атрибут HTML5 data, data-project-id="{{this.id}}", к элементу figure, который оборачивает изображение с эскизом проекта портфолио, следующим образом:
1 |
... |
2 |
<figure class="portfolio-cover" title="{{this.name}}" data-project-id="{{this.id}}"> |
3 |
{{#if this.covers.[404]}}
|
4 |
<img class="portfolio-image" src="{{this.covers.[404]}}" alt=""> |
5 |
{{else}}
|
6 |
{{#if this.covers.[230]}}
|
7 |
<img class="portfolio-image" src="{{this.covers.[230]}}" alt=""> |
8 |
{{else}}
|
9 |
<img class="portfolio-image" src="{{this.covers.[202]}}" alt=""> |
10 |
{{/if}}
|
11 |
{{/if}}
|
12 |
</figure>
|
13 |
... |
Обновите страницу и проинспектируйте веб-сайт при помощи Chrome DevTools или Firebug. Вы должны будете обнаружить, что data-project-id содержит ID проекта портфолио, как показано ниже:



Мы воспользуемся атрибутом data для получения контента выбранного проекта портфолио с присвоенным ему ID позже.
После этого нам также нужно будет изменить вид курсора на курсор в виде линзы с плюсиком следующим образом:
1 |
...
|
2 |
.portfolio-cover { |
3 |
cursor: pointer; |
4 |
cursor: -webkit-zoom-in; |
5 |
cursor: -moz-zoom-in; |
6 |
cursor: zoom-in; |
7 |
width: 100%; |
8 |
}
|
9 |
...
|
Благодаря нему пользователю будет дана подсказка, что для изображения имеется возможность увеличения; пользователи должны полагать, что могут нажать по изображению. Однако согласно MDN (* Mozilla Developer Network) значение zoom-in еще не поддерживается ни в какой версии Internet Explorer.Mozilla Developer Network Поэтому мы также указали в качестве значения cursor значение pointer (* курсор-рука – используется для сообщения пользователю, что под ним находится гиперссылка) перед cursor: zoom-in в качестве запасного варианта для Internet Explorer и других браузеров, в которых, возможно, нет поддержки cursor: zoom-in.
Запускаем Magnific Popup
Теперь мы добавим скрипт для инициализации Magnific Popup. Поскольку нашей целью является не только показ изображения с эскизом проекта портфолио, но и остальных изображений проекта, скрипт, вероятно, будет выглядеть слегка объемным. Поэтому мы будем добавлять его код постепенно. Первое, что мы напишем – метод .on('click') jQuery. Magnific Popup будет запускаться только при нажатии пользователем по изображению с эскизом.
1 |
$('#portfolio').on('click', '.portfolio-cover', function() { |
2 |
//the rest of the script goes here...
|
3 |
}
|
Далее мы определим следующие переменные:
- переменная
$thisсодержит ссылку на объект, к которому прицеплен метод.on(). - в
projectIDбудет содержаться результат, возвращаемый методом$this.data('project-id'), при помощи которого извлекается ID выбранного проекта из атрибутаdata-project-id. Мы будем его использовать для получение контента при помощи API Behance. - в
beProjectContentAPIбудет содержаться конечная точка (* отдельная функция API) API Behance для получения контента проекта Behance. - в
keyNameбудет находиться ключевое имя, которое мы будем использовать для сохранения данных, полученных с Behance, в localStorage. Формат имени будет следующим:behanceProjectImages-, за которым следует ID проекта. В противоположность тому, что мы делали ранее, теперь мы используем localStorage для сохранения данных, а не sessionStorage. Это так, поскольку мы предполагаем, что пользователи Behance редко бы обновляли контент после его опубликования. Так что в данном случае нам лучше использовать localStorage, поскольку в нем данные будут сберегаться постоянно; данные будут оставаться в браузере до тех пор, пока мы их целенаправленно не удалим.
1 |
$('#portfolio').on('click', '.portfolio-cover', function() { |
2 |
var $this = $(this), |
3 |
projectID = $this.data('project-id'), |
4 |
beProjectContentAPI = 'http://www.behance.net/v2/projects/'+ projectID +'?callback=?&api_key=' + apiKey, |
5 |
keyName = 'behanceProjectImages-' + projectID; |
6 |
}
|
Затем мы создаем главную функцию, при помощи которой будет запущен код Maginific Popup. Мы назовем ее showGallery(). Также мы применим следующие опции для Magnific Popup:
-
items; эта опция очень важна. В этом свойстве будет содержаться список изображений, которые будут отображаться в модальном окне. -
gallery; при активации этой опции будут добавлены стрелки для просмотра содержащихся в проекте изображений. -
type; в качестве типа контента, который разрешено использовать в модальном окне, мы будем использовать изображение.
Последний фрагмент кода неизбежен; нам необходимо будет добавить .magnificPopup('open'), чтобы за счет него немедленно было открыто модальное окно после инициализации.
1 |
$('#portfolio').on('click', '.portfolio-cover', function() { |
2 |
var $this = $(this), |
3 |
projectID = $this.data('project-id'), |
4 |
beProjectContentAPI = 'http://www.behance.net/v2/projects/'+ projectID +'?callback=?&api_key=' + apiKey, |
5 |
keyName = 'behanceProjectImages-' + projectID; |
6 |
|
7 |
function showGallery(dataSource) { |
8 |
$this.magnificPopup({ |
9 |
items: dataSource, |
10 |
gallery: { |
11 |
enabled: true |
12 |
},
|
13 |
type: 'image' |
14 |
}).magnificPopup('open'); |
15 |
};
|
16 |
}
|
Мы будем запускать showGallery() только при определенных условиях; если данные для выбранного проекта портфолио доступны в localStorage, то необходимо будет получить их и выполнить showGallery(), в ином случае нужно получить для начала данные через API при помощи $.getJSON(), затем выполнить showGallery() и сохранить эти данные в localStorage для дальнейшего использования. Как и ранее, нам необходимо воспользоваться JSON.stringify() для преобразования данных в строку, благодаря чему их можно будет сохранить в localStorage, а затем мы воспользуемся JSON.parse() для преобразования их обратно в объект JSON.
Проверяем, что пришедший контент – изображения
Здесь следует отметить, что в качестве поступающего через API контента может быть видео, встроенное видео или текст, которые нам не подходят; нам нужны только изображения. Поэтому перед отправлением данных в localStorage нам необходимо добавить следующий фрагмент кода для фильтрации контента:
1 |
var src = []; |
2 |
$.each(projectContent.project.modules, function(index, mod) { |
3 |
if(mod.src != undefined) { |
4 |
src.push({ src: mod.src }); |
5 |
}
|
6 |
});
|
Ниже приводится финальный код всего скрипта:
1 |
$('#portfolio').on('click', '.portfolio-cover', function() { |
2 |
var $this = $(this), |
3 |
projectID = $this.data('project-id'), |
4 |
beProjectContentAPI = 'http://www.behance.net/v2/projects/'+ projectID +'?callback=?&api_key=' + apiKey, |
5 |
keyName = 'behanceProjectImages-' + projectID; |
6 |
|
7 |
function showGallery(dataSource) { |
8 |
$this.magnificPopup({ |
9 |
items: dataSource, |
10 |
gallery: { |
11 |
enabled: true |
12 |
},
|
13 |
type: 'image' |
14 |
}).magnificPopup('open'); |
15 |
};
|
16 |
|
17 |
if(localStorage.getItem(keyName)) { |
18 |
var srcItems = JSON.parse(localStorage.getItem(keyName)); |
19 |
showGallery(srcItems); |
20 |
} else { |
21 |
$.getJSON(beProjectContentAPI, function(projectContent) { |
22 |
var src = []; |
23 |
$.each(projectContent.project.modules, function(index, mod) { |
24 |
if(mod.src != undefined) { |
25 |
src.push({ src: mod.src }); |
26 |
}
|
27 |
});
|
28 |
showGallery(src); |
29 |
var data = JSON.stringify(src); |
30 |
localStorage.setItem(keyName, data); |
31 |
});
|
32 |
};
|
33 |
});
|
Если вы теперь нажмете изображение, то его масштаб должен будет увеличиться и оно должно будет быть отображено в стиле модального окна:



Если вы проинспектируете веб-сайт при помощи Chrome DevTools, вы должны будете обнаружить, что контент хранится в localStorage.



К тому же вы можете просмотреть все изображения контента проекта при помощи стрелок. Однако переход между изображениями сейчас происходит довольно неудобно (верно?); мы переходим от одного изображения к другому мгновенно. Так что давайте сделаем его более плавным при помощи анимаций, хорошо?
Добавляем Animate.css
Для начала нам необходимо будет добавить mainClass: 'animated' и removalDelay: 350 в нашу функцию magnificPopup.
1 |
...
|
2 |
function showGallery(dataSource) { |
3 |
$this.magnificPopup({ |
4 |
items: dataSource, |
5 |
gallery: { |
6 |
enabled: true |
7 |
},
|
8 |
type: 'image', |
9 |
mainClass: 'animated', |
10 |
removalDelay: 350 |
11 |
}).magnificPopup('open'); |
12 |
};
|
13 |
...
|
В этом коде мы добавили новый класс под названием animated к нашему модальному окну. Класс animated используется в Animate.css для назначения анимации какому-то элементу. Этот класс также мог бы быть полезен для активации или отключения анимации, когда вам это необходимо; если вы хотите отключить ее, то просто удалите строку с mainClass: 'animated'.
Также мы добавили removalDelay, при помощи которого указывается время, которое пройдет до того, как модальное окно будет полностью удалено из DOM. За счет этой задержки у пользователя будет возможность заметить анимацию.
Подгоняем стилевое оформление для ключевых кадров
Далее мы настроим несколько ключевых кадров (* кадр, создаваемый при изменении атрибута, чтобы зафиксировать его новое состояние, например, начало или конец нужной траектории перемещения, смену материала и т. п.) CSS, переходов и трансформаций, за счет которых создается эффект анимации при помощи Animate.css. Мы сконвертируем их код CSS в формат LESS, используя LESSHat.
Давайте начнем с ключевых кадров.
1 |
.keyframes(~'fadeInRight, 0% { transform: translateX(20px); opacity: 0; } 100% { transform: translateX(0); opacity: 1; }'); |
2 |
.keyframes(~'fadeInLeft, 0% { transform: translateX(-20px); opacity: 0; } 100% { transform: translateX(0); opacity: 1; }'); |
3 |
|
4 |
.keyframes(~'fadeOutRight, 0% { transform: translateX(0); opacity: 1; } 100% { transform: translateX(20px); opacity: 0; }'); |
5 |
.keyframes(~'fadeOutLeft, 0% { transform: translateX(0); opacity: 1; } 100% { transform: translateX(-20px); opacity: 0; }'); |
6 |
|
7 |
.keyframes(~'fadeInDown, 0% { transform: translateY(-20px); opacity: 0; } 100% { transform: translateY(0); opacity: 1; }'); |
8 |
.keyframes(~'fadeOutDown, 0% { transform: translateY(0); opacity: 1; } 100% { transform: translateY(20px); opacity: 0; }'); |
Мы добавили несколько ключевых кадров под названиями fadeInRight, fadeInLeft, fadeOutRight, fadeOutLeft, fadeInDown и fadeOutDown, код которых был преобразован в код формата LESS при помощи миксинов .keyframes() LESSHat.
В модальном окне имеется несколько частей, которые мы будем анимировать, а именно: верхний слой фона, который покрывает все окно просмотра (* видимая для пользователя область веб-страницы), контент модального окна (изображение) и стрелки для просмотра изображений.
Анимацию верхнего слоя фона довольно легко выполнить. Для ее реализации вовсе не нужны указанные выше ключевые кадры, фон просто будет постепенно проявляться при появлении модального окна и постепенно пропадать при его исчезновении. Ниже представлены все стилевые правила для реализации этой анимации.
1 |
.mfp-bg.animated { |
2 |
opacity: 0; |
3 |
.transition(opacity 350ms ease-out); |
4 |
}
|
5 |
.mfp-bg.mfp-ready.animated { |
6 |
opacity: 0.8; |
7 |
}
|
8 |
.mfp-bg.mfp-removing.animated { |
9 |
opacity: 0; |
10 |
}
|
В Magnific Popup для верхнего слоя фона задан класс под названием mfp-bg. В вышеуказанном коде мы устанавливаем в качестве значения его прозрачности 0, так что изначально фон будет невидимым, а также задаем продолжительность перехода для свойства opacity.
Кроме этого за счет Magnific Popup будет добавлен набор новых классов для определения поведения элемента при наступлении различных состояний; например при полном появлении модального окна будет добавлен класс mfp-ready. Для этого состояния мы указали в качестве значения прозрачности 0.8. Поскольку мы установили значение для перехода, то в результат получится эффект анимации; прозрачность будет изменяться от 0 до 0.8 за 350 ms.
Затем после исчезновения модального окна при помощи Magnific Popup будет добавлен класс mfp-removing. Для этого состояния мы изменяем значение прозрачности обратно (0), благодаря чему верхний слой фона снова становится невидимым.
Ниже приводятся стилевые правила для реализации анимации контента модального окна.
1 |
.mfp-wrap.animated .mfp-content { |
2 |
.animation-duration(350ms);
|
3 |
}
|
4 |
.mfp-wrap.animated .mfp-content { |
5 |
.animation-name(fadeInDown);
|
6 |
}
|
7 |
.mfp-wrap.mfp-removing.animated .mfp-content { |
8 |
.animation-name(fadeOutDown);
|
9 |
}
|
Как и в случае с верхним слоем фона, мы также задали для контента в качестве значения продолжительности перехода 350 ms. Также мы применяем ключевые кадры при помощи миксина .animation-name(). За счет этого кода контент будет при показе постепенно появляться и в тоже время опускаться сверху, а затем при исчезновении опускаться вниз и постепенно пропадать.
Анимация стрелок для перехода между изображениями
Наконец, мы добавим анимацию для стрелок
1 |
.mfp-wrap.animated .mfp-arrow { |
2 |
.animation-duration(350ms);
|
3 |
}
|
4 |
.mfp-wrap.animated .mfp-arrow-left { |
5 |
.animation-name(fadeInRight);
|
6 |
}
|
7 |
.mfp-wrap.mfp-removing.animated .mfp-arrow-left { |
8 |
.animation-name(fadeOutLeft);
|
9 |
}
|
10 |
.mfp-wrap.animated .mfp-arrow-right { |
11 |
.animation-name(fadeInLeft);
|
12 |
}
|
13 |
.mfp-wrap.mfp-removing.animated .mfp-arrow-right { |
14 |
.animation-name(fadeOutRight);
|
15 |
}
|
Этот код довольно подобен фрагменту, при помощи которого реализуется анимация для контента. Согласно нему при показе левая стрелка будет постепенно появляться и выходить справа, затем уходить влево и постепенно пропадать. С правой стрелкой будет происходить обратное.
Заключение
Это была очень длинная серия руководств! Мы успешно создали рабочий вебсайт с персональным портфолио с нуля, используя в качестве источника данных API Behance. Для того чтобы его создать, мы также воспользовались рядом современных инструментов вроде LESS, HandlebarsJS и Animate.css. Этот веб-сайт довольно легко закачать на сервер, поскольку он состоит всего лишь из одной статической HTML-страницы – и вправду, демоверсия нашего сайта располагается на сервере GitHub в качестве статической страницы. Также вы можете закачать ее на веб-сервер при помощи FTP.
Если вы хотите усовершенствовать этот проект, то вы можете добавить например «фильтр», благодаря которому проекты порфолио будут отсортированы в соответствии с выбранной областью творческой деятельности. Также вы могли бы добавить изящные эффекты, возникающие при наведении курсора поврех элементов. Как бы там ни было, надеюсь, что вам понравилась эта серия и вы овладели несколькими приемами, которыми сможете воспользоваться при создании вашего собственного веб-сайта.



