Создадим анимированное меню для сайта ресторана. Сделаем пункты меню анимированными, и при клике на один из них будет выплывать окошко с информацией. А фоновое изображение будет менять цвет, в зависимости от открытого меню. Меню ресторана будет отображено в категориях. В блоке будет находится информация про напитки или блюда. После появления блока, меню будет скрываться. При закрытии контента, меню снова будет отображаться.
Структура
В 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”. Тут поместим заголовок и список без нумерации для пунктов меню, спрятанный в div с классом “ac_menu”.
<div id="ac_content" class="ac_content">
<h1><span>Cafe + Bar</span>Dhalia</h1>
<div class="ac_menu">
<ul>
<li>
<a href="images/Appetizers.jpg">Appetizers</a>
<div class="ac_subitem">
<span class="ac_close"></span>
<h2>Appetizers</h2>
<ul>
<li>
A wonderful serenity has taken possession
of my entire soul, like these sweet mornings
of spring which I enjoy with my whole heart.
</li>
<li>Lobster Bisque</li>
<li>Smoked Salmon Terrine</li>
<li>Tuna Ceviche</li>
<li>Wild Mushroom Flan</li>
<li>Almond Bruschetta</li>
<li>Green Chilli Canapee</li>
<li>Artichoke Rucula Salad</li>
</ul>
</div><!-- ac_subitem-->
</li>
...
</ul>
</div><!-- ac_menu -->
</div><!-- ac_content -->
Каждому пункту меню создается блок div с классом “ac_subitem” с необходимой информацией. Сюда также можно помещать другой список или любой другой контент.
Ссылки главного меню будут направлять к изображениям, которые будут отображаться при нажатии на нужный пункт меню.
Перейдем к стилям
CSS
Самым первым подключим файл reset.css:
@import url('reset.css');
Фон элемента body сделаем черным, тогда при изменении изображения, фон будет темнеть.
body{
background:#000;
color:#fff;
font-family: 'PT Sans Narrow', Arial, sans-serif;
text-transform:uppercase;
}
Сделаем цвет под ссылками белым цветом:
a{
color:#fff;
text-decoration:none;
}
Фоновые изображения назначаются через JavaScript. Расположения и размеры изображений будут динамическими и будут зависеть от величины мониторов пользователей.
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:transparent url(../images/pattern.png) repeat top left;
}
Иконку загрузки помещаем в верхний правый угол. Ее увидим при смене изображения.
.ac_loading{
position:fixed;
top:10px;
right:10px;
background:#000 url(../images/loader.gif) no-repeat center center;
width:50px;
height:50px;
border-radius:10px 10px 10px 10px;
z-index:999;
opacity:0.7;
display:none;
}
Блок с контентом расположен по центру. Для этого нужно атрибуту top присвоить значение 50% и уменьшить его высоту, сделав 50%.
.ac_content{
position:fixed;
height:90px;
width:100%;
top:50%;
left:0px;
margin-top:-65px;
}
Фон внизу заголовка делаем полупрозрачным черным. Стили h1 и span определяем отдельно. Справа добавляем рамку в 1 пиксель.
.ac_content h1{
background:transparent url(../images/bg_menu.png) repeat top left;
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) repeat top left;
float:left;
position:relative;
height:90px;
width:0px;
}
Определям стиль для списка без нумерации:
.ac_menu > ul{
float:right;
Для высоты элементов зададим атрибут overflow: hidden. Если их упустить, ссылки будут видны во время анимации:
.ac_menu > ul > li{
float:left;
position:relative;
height:90px;
overflow:hidden;
}
Ссылки скрыты с помощью атрибутов margin-top и opacity. Мы их перемещаем на середину (margin-top: 0px) и делаем их видимыми, задав значению opacity увеличение. Ссылки будут немного задерживаться, это придает виду интересный эффект.
.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;
}
Изначально блоки с иформацией имеют ширину 400 пикселей и высоту 0 пикселей. Плавно увеличиваем это значение и margin-top, чтобы из середины выплывало окошко.
.ac_subitem{
width:400px;
height:0px; /* animate to 400px */
top:50%;
right:0px;
margin-top:0px; /* animate to -200px */
position:fixed;
z-index:99;
overflow:hidden;
background:transparent url(../images/bg_menu.png) repeat top left;
}
Для блока с контентом определим некоторые стили:
.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:transparent url(../images/close.png) no-repeat top left;
opacity:0.4;
}
span.ac_close:hover{
opacity:1.0;
}
Переходим к анимации.
JavaScipt
Используем дополнительный плагин. Его нужно сразу подключить после подключения 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() {
/*
1- загружает все фоновые и другие изображения;
2- отображает фоновое изображение;
3- скрывает и открывает меню;
4- отображает пункты меню;
5- инициализирует события, связанные с пунктами меню
*/
$ac_loading.show(); //отображение иконки загрузки
$.when(loadImages()).done(function(){
$.when(showBGImage()).done(function(){
//скрывает иконку загрузки
$ac_loading.hide();
$.when(slideOutMenu()).done(function(){
$.when(toggleMenuItems('up')).done(function(){
initEventsSubMenu();
});
});
});
});
},
showBGImage = function() {
return $.Deferred(
function(dfd) {
//подсчитывает размеры изображения
adjustImageSize($ac_bgimage);
$ac_bgimage.fadeIn(1000, dfd.resolve);
}
).promise();
},
slideOutMenu = function() {
/* подсчитывает новую ширину меню */
var new_w = $(window).width() - $title.outerWidth(true);
return $.Deferred(
function(dfd) {
//скрывает меню
$menu.stop()
.animate({
width : new_w + 'px'
}, 700, dfd.resolve);
}
).promise();
},
/* скрывает / отображает пункт меню */
toggleMenuItems = function(dir) {
return $.Deferred(
function(dfd) {
/*
скрывает / отображает пункты меню.
каждый раз разная анимация.
*/
$menuItems.each(function(i) {
var $el_title = $(this).children('a:first'),
marginTop, opacity, easing;
if(dir === 'up'){
marginTop = '0px';
opacity = 1;
easing = 'easeOutBack';
}
else if(dir === 'down'){
marginTop = '60px';
opacity = 0;
easing = 'easeInBack';
}
$el_title.stop()
.animate({
marginTop : marginTop,
opacity : opacity
}, 200 + i * 200 , easing, function(){
if(i === totalItems - 1)
dfd.resolve();
});
});
}
).promise();
},
initEventsSubMenu = function() {
$menuItems.each(function(i) {
var $item = $(this), //
$el_title = $item.children('a:first'),
el_image = $el_title.attr('href'),
$sub_menu = $item.find('.ac_subitem'),
$ac_close = $sub_menu.find('.ac_close');
/* пользователь кликает по пункту меню */
$el_title.bind('click.Menu', function(e) {
$.when(toggleMenuItems('down')).done(function(){
openSubMenu($item, $sub_menu, el_image);
});
return false;
});
/* контент скрывается */
$ac_close.bind('click.Menu', function(e) {
closeSubMenu($sub_menu);
return false;
});
});
},
openSubMenu = function($item, $sub_menu, el_image) {
$sub_menu.stop()
.animate({
height : '400px',
marginTop : '-200px'
}, 400, function() {
//the bg image changes
showItemImage(el_image);
});
},
/* меняется фоновое изображение */
showItemImage = function(source) {
//если это текущее изображение, то вернет 0
if($ac_bgimage.attr('src') === source)
return false;
var $itemImage = $('');
$itemImage.insertBefore($ac_bgimage);
adjustImageSize($itemImage);
$ac_bgimage.fadeOut(1500, function() {
$(this).remove();
$ac_bgimage = $itemImage;
});
$itemImage.fadeIn(1500);
},
closeSubMenu = function($sub_menu) {
$sub_menu.stop()
.animate({
height : '0px',
marginTop : '0px'
}, 400, function() {
//отображение элементов
toggleMenuItems('up');
});
},
/*
on window resize, ajust the bg image dimentions,
and recalculate the menus width
*/
initWindowEvent = function() {
/* назначает ширину фонового изображения */
$(window).bind('resize.Menu' , function(e) {
adjustImageSize($ac_bgimage);
/* считает новую ширину меню */
var new_w = $(window).width() - $title.outerWidth(true);
$menu.css('width', new_w + 'px');
});
},
/* расширяет изображение и располагает его по центру */
adjustImageSize = function($img) {
var w_w = $(window).width(),
w_h = $(window).height(),
r_w = w_h / w_w,
i_w = $img.width(),
i_h = $img.height(),
r_i = i_h / i_w,
new_w,new_h,
new_left,new_top;
if(r_w > r_i){
new_h = w_h;
new_w = w_h / r_i;
}
else{
new_h = w_w * r_i;
new_w = w_w;
}
$img.css({
width : new_w + 'px',
height : new_h + 'px',
left : (w_w - new_w) / 2 + 'px',
top : (w_h - new_h) / 2 + 'px'
});
},
/* загружает все изображения */
loadImages = function() {
return $.Deferred(
function(dfd) {
var total_images = $ItemImages.length,
loaded = 0;
for(var i = 0; i < total_images; ++i){
$('').load(function() {
++loaded;
if(loaded === total_images)
dfd.resolve();
}).attr('src' , $ItemImages[i]);
}
}
).promise();
};
return {
init : init
};
})();
/*
вызов метода init
*/
Menu.init();
Все. Вы научились делать анимированное меню.




а где же демо