Сегодня мы создадим отличное анимированное меню для не отягощенного информацией сайта. Это может быть сайт небольшого кафе/чайного клюба или портфолио фотографа/художника-иллюстратора. Пункты нашего меню будут анимированы, а нажатие на них приведет к появлению окошка с контентом. Более того, фоновое изображение будет меняться в зависимости от выбранного пункта меню
Структура меню
В HTML у нас будут несколько элементов для фонового изображения, сетки, перекрывающей его, иконки загрузки и главного меню. Структура будет такой:
<div id="ac_background" class="ac_background">
<img class="ac_bgimage" src="images/Default.jpg" alt="Фон"/>
<div class="ac_overlay"></div>
<div class="ac_loading"></div>
</div>
После загрузки страницы отобразится дефолтное изображение. Не мурдствуя лукаво назовем его default.jpg
. При клике по какому-то пункту меню фоновое изображение будет перекрываться другим, а само оно исчезнет. Меню заключим в блок div и присвоим ему класс ac_content
. В этот блок поместим заголовок в теге h2 и ненумерованный список ul для пунктов меню. Список обернем тегом div
и назначим ему класс ac_menu
.
<div id="ac_content" class="ac_content">
<h1><span>Фотограф</span>Дмитрий</h1>
<div class="ac_menu">
<ul>
<li>
<a href="images/studiny-fotograf.jpg">Студийный фотограф</a>
<div class="ac_subitem">
<span class="ac_close"></span>
<h2>Студийный фотограф</h2>
<ul>
<li>Четкое соблюдение сроков обработки фотографии от 1 дня</li>
<li>Фотограф с профильным образованием и опытом работы более 5 лет</li>
<li>Мы любим свою работу и вкладываем частичку себя в каждую съемку</li>
</ul>
</div><!-- ac_subitem-->
</li>
...
</ul>
</div><!-- ac_menu -->
</div><!-- ac_content -->
Для каждого пункта меню создадим блок div
, имеющий класс ac_subitem
. В этом блоке будет содержаться наш текст. Сюда же мы поместим другой список (хотя, не обязательно список, можно и текст и картинки - да все, что угодно!). Ссылки в главном меню будут вести к изображениям, которые отобразятся при клике на соответствующий пункт меню. Более правильно, конечно, воспользоваться атрибутом data, но, раз у нас атрибут href пустует, то запихнем путь к изображениям в него. Теперь давайте поиграемся со стилями чтобы наша страница не напоминала сайты эпохи начала интернета.
С CSS пришел прогресс!
В самом начале давайте подключим файл reset.css чтобы избавиться от нежелательных отступов, которые подсовывают нам браузеры:
@import url('reset.css');
Фоновый цвет элемента body будет черным, чтобы чтобы исходное изображение зтемнялась во время замены на другое.
body{
background:#000;
color:#fff;
font-family: Arial, sans-serif;
text-transform:uppercase;
}
Ссылки у нас будут белого цвета и без подчеркивания (правда, последнее очень не рекомендуется дизайнерами):
a{
color:#fff;
text-decoration:none;
}
Фоновые изображения будут назначаться с помощью JavaScript, поэтому мы не назначим ни одного из них через CSS. Размеры и расположение изображений также будут считаться динамически и будут зависеть от размеров пользовательских мониторов:
img.ac_bgimage{
position:fixed;
left:0px;
top:0px;
opacity:0.8;
display:none;
}
Облагородим наше изображение с помощью специального паттерна:
.ac_overlay{
width:100%;
height:100%;
position:fixed;
top:0px;
left:0px;
background: url(../images/pattern.png);
}
Блок с контентом расположим в центре страницы, для этого присвоим атрибуту top значение 50%
и уменьшим его высоту, присвоив атрибуту margin-top значение -45px
. Так он расположится прямо по центру:
.ac_content{
position:fixed;
height:90px;
width:100%;
top:50%;
left:0px;
margin-top:-45px;
}
Фон под заголовком слева будет черного цвета и полу-прозрачным. Стили для заголовка h1 и span мы определим отдельно. Давайте еще сделаем справа рамку толщиной в 1 пиксель, чтобы меню было отделено от заголовка (сделать это можно с помощью CSS свойств border-right или margin-right):
.ac_content h1{
background:transparent url(../images/bg_menu.png);
display:block;
float:left;
width:90px;
height:50px;
padding:20px;
font-size:36px;
font-weight:bold;
line-height:20px;
margin-right:1px;
}
.ac_content h1 span{
display:block;
font-weight:normal;
font-size:14px;
}
Фон блока меню будет таким же. Его начальная ширина будет 0 пикселей, а увеличивать ее до ширины окна при загрузке страницы мы будем с помощью JavaScript:
.ac_menu{
background:transparent url(../images/bg_menu.png);
float:left;
position:relative;
height:90px;
width:0px;
}
Для ненумерованного списка с пунктами меню определим такой стиль:
.ac_menu > ul{
float:right;
}
Высота элементов списка будет подсчитана определенным образом, для них мы также зададим стиль overflow, равный hidden
, так как нам необходимо, чтобы они выплывали снизу. Если не задать overflow: hidden
, то ссылки будут видны во время анимации:
.ac_menu > ul > li{
float:left;
position:relative;
height:90px;
overflow:hidden;
}
Изначально ссылки будут скрыты с помощью задания CSS свойств margin-top
и opacity. Потом мы плавно переместим их на середину (margin-top: 0px
) и сделаем их видимыми (opacity: 1
). Причем сделаем это так, чтобы они немножко задерживались, тем самым создадим интересный эффект:
.ac_menu > ul > li a{
margin-top:60px;
opacity:0;
display:block;
height:90px;
padding:0px 10px;
text-align:center;
line-height:90px;
outline:none;
font-size:18px;
font-weight:bold;
text-shadow:1px 1px 1px #000;
}
Блоки с контентом будут шириной в 400px
и начальной высотой 0px
. Для создания эффекта плавного появления окна из середины страницы мы будем плавно увеличивать выcоту height и margin-top
:
.ac_subitem{
width:400px;
height:0px; /* анимируем, изменяя до 400px */
top:50%;
right:0px;
margin-top:0px; /* анимируем, изменяя до -200px */
position:fixed;
z-index:99;
overflow:hidden;
background:transparent url(../images/bg_menu.png);
}
Поработаем теперь над блоком с контентом:
.ac_subitem h2{
font-size:22px;
font-weight:bold;
color:#fff;
padding: 40px 0px 0px 40px;
text-shadow:0px 0px 1px #000;
}
.ac_subitem ul{
padding:0px 40px;
}
.ac_subitem ul li{
margin:10px 0px;
}
.ac_subitem ul li:first-child{
font-size:14px;
text-transform:none;
border-bottom:1px dotted #333;
padding-bottom:15px;
margin-bottom:15px;
}
Для закрытия блока у нас предусмотрена кнопка. Образмерим ее и поместим в правый верхний угол, а еще добавим иконку ввиде крестика:
span.ac_close{
float:right;
margin:10px;
width:11px;
height:12px;
cursor:pointer;
background: url(../images/close.png) no-repeat;
opacity:0.4;
}
span.ac_close:hover{
opacity:1.0;
}
Итак, со стилями мы разобрались. Давайте теперь займемся анимацией.
Анимация с помощью JavaScipt
Для анимации мы воспользуемся специальным плагином jQuery Easing. Подключите его сразу после подключения jQuery. Подключили? Отлично. Теперь давайте объявим переменные:
var $ac_background = $('#ac_background'),
$ac_bgimage = $ac_background.find('.ac_bgimage'),
$ac_loading = $ac_background.find('.ac_loading'),
$ac_content = $('#ac_content'),
$title = $ac_content.find('h1'),
$menu = $ac_content.find('.ac_menu'),
$mainNav = $menu.find('ul:first'),
$menuItems = $mainNav.children('li'),
totalItems = $menuItems.length,
$ItemImages = new Array();
Загрузим все изображения, для этого добавим все ссылки, а также дополнительно объявим текущее изображение:
$menuItems.each(function(i) {
$ItemImages.push($(this).children('a:first').attr('href'));
});
$ItemImages.push($ac_bgimage.attr('src'));
Это была присказка, теперь мы займемся серьезными вещами и напишем нашу главную функцию (приводится с сокращениями, полный код можно увидеть в скаченном архиве, или при просмотре примера):
var Menu = (function(){
var init = function() {
loadPage();
initWindowEvent();
},
/* загружает все фоновые и другие изображения, ини-
/* циализирует события, связанные с пунктами меню */
loadPage = function() {
...
},
/* Показывает изображения */
showBGImage = function() {
...
},
/* Скрывает меню */
slideOutMenu = function() {
...
},
/* Скрывает, либо отображает пункт меню */
toggleMenuItems = function(dir) {
...
},
/* Инициализируем события подменю */
initEventsSubMenu = function() {
...
},
/* Открываем подменю */
openSubMenu = function($item, $sub_menu, el_image) {
...
},
/* Меняется фоновое изображение */
showItemImage = function(source) {
...
},
/* Закрываем подменю */
closeSubMenu = function($sub_menu) {
...
},
/* При изменении размеров окна пересчитаем */
/* ширину меню и размер изображения */
initWindowEvent = function() {
...
},
/* Расширяет и центрирует изображение */
adjustImageSize = function($img) {
...
},
/* Загружает все изображения */
loadImages = function() {
...
};
return {
init : init
};
})();
/* Вызов метода init */
Menu.init();
Наш урок окончен. Скорее показывайте меню клиенту и срывайте аплодисменты!
Улучшения
Если вы внимательно изучили код (а не тупо его скопировали), вы могли заметить, что мы делаем лишние телодвижения. А именно растягиваем изображение с соблюдением пропорций и центрируем его относительно экрана. Можно сделать намного проще: вместо изображения вставлять блочный элемент, растянутый на весь экран (это делается через CSS). Фоном этого блока будет служить наше изображение, смасштабированное с помощью CSS свойства background-size (не забудьте про префиксы). Таким образом, мы сможем избавиться от функции adjustImageSize
. Проделать все это я предоставляю вам самим. Надеюсь, вы справитесь!