Сегодня мы расскажем вам о том, как создать привлекательное меню с красивой анимацией, воспроизводимой при наведении курсора мыши. Здесь принцип заключается в том, чтобы некоторые из элементов выезжали и изменялись, а фоновый цвет каждого пункта изменялся, а затем эти элементы возвращались в исходную позицию, но уже с другим цветом.
Вдохновение на создание подобного эффекта пришло к нам при виде Pelican Miami Beach Hotel: http://www.pelicanhotel.com/
Иконки были взяты из невероятного Noun Project, который «собирает, сортирует и добавляет всевозможные обозначения, способствующие приданию значения иконкам». Не забудьте посетить официальный веб-сайт The Noun Project.
Итак, приступим!
Каркас
В нашем HTML-коде будет неупорядоченный список, где каждый пункт списка будет содержать анкор с тремя элементами внутри него, их мы и будем анимировать:
<ul id="sti-menu" class="sti-menu">
<li data-hovercolor="#37c5e9">
<a href="#">
<h2 data-type="mText" class="sti-item">
Some text
</h2>
<h3 data-type="sText" class="sti-item">
Some more text
</h3>
<span data-type="icon" class="sti-icon sti-icon-care sti-item">
</span>
</a>
</li>
<li>...</li>
...
</ul>
data-hovercolor будет использован для назначения цвета текста при наведении. Мы также внесем атрибут data-type к каждому заголовку и спану с иконкой. Это мы будем использовать позже в коде javascript.
Теперь давайте займёмся оформлением!
CSS-код
Помните, что всегда сначала нужно сбрасывать параметры с помощью reset.css, - его мы добавляем в наш основной стиль.
Сначала мы оформим неупорядоченный список и зададим ему фиксированную ширину для того, чтобы у нас была возможность центрировать его на странице:
.sti-menu{
width:1010px;
position:relative;
margin:60px auto 0 auto;
}
Элементы списка будут парящими и им будет задано небольшое поле:
.sti-menu li{
float:left;
width:200px;
height:300px;
margin:1px;
}
Теперь нужно оформить анкор. Мы спрячем все, что выходит за границы, так как нам нужно анимировать элементы за пределами анкора:
.sti-menu li a{
display:block;
overflow:hidden;
background:#fff;
text-align:center;
height:100%;
width:100%;
position:relative;
-moz-box-shadow:1px 1px 2px #ddd;
-webkit-box-shadow:1px 1px 2px #ddd;
box-shadow:1px 1px 2px #ddd;
}
Заголовкам будет задано абсолютное позиционирование, и мы определим ширину в верхней позиции:
.sti-menu li a h2{
color:#000;
font-family: 'Wire One', arial, serif;
font-size:42px;
font-weight:bold;
text-transform:uppercase;
position:absolute;
padding:10px;
width:180px;
top:140px;
text-shadow: 0px 1px 1px black;
}
.sti-menu li a h3{
font-family: Baskerville, "Hoefler Text", Garamond, "Times New Roman", serif;
font-size:18px;
font-style:italic;
color: #111;
position:absolute;
top:248px;
width:180px;
padding:10px;
}
Каждому спану иконки будет присвоен последующий класс, а также один специальный, в котором будет задано правильное фоновое изображение. Изображения будут состоять как из цветных, так и из черных иконок. Мы изменим расположение фона посредством javascipt, как только анимируем иконку за пределами анкора.
.sti-icon{
width:100px;
height:100px;
position:absolute;
background-position:top left;
background-repeat:no-repeat;
background-color:transparent;
left:50px;
top:30px;
}
.sti-icon-care{
background-image:url(../images/care.png);
}
.sti-icon-alternative{
background-image:url(../images/alternative.png);
}
.sti-icon-family{
background-image:url(../images/family.png);
}
.sti-icon-info{
background-image:url(../images/info.png);
}
.sti-icon-technology{
background-image:url(../images/technology.png);
}
Вот и всё, что касается оформления! Теперь начинается все самое интересное!
javascript
Так как здесь мы используем плагин, давайте для начала зададим настройки по умолчанию:
var settings = {
// configuration for the mouseenter event
animMouseenter : {
'mText' : {speed : 350, easing : 'easeOutExpo', delay : 140, dir : 1},
'sText' : {speed : 350, easing : 'easeOutExpo', delay : 0, dir : 1},
'icon' : {speed : 350, easing : 'easeOutExpo', delay : 280, dir : 1}
},
// configuration for the mouseleave event
animMouseleave : {
'mText' : {speed : 300, easing : 'easeInExpo', delay : 140, dir : 1},
'sText' : {speed : 300, easing : 'easeInExpo', delay : 280, dir : 1},
'icon' : {speed : 300, easing : 'easeInExpo', delay : 0, dir : 1}
},
// speed for the item bg color animation
boxAnimSpeed : 300,
// default text color (same defined in the css)
defaultTextColor : '#000',
// default bg color (same defined in the css)
defaultBgColor : '#fff'
};
Для каждого из наших элементов у нас будет указана скорость анимации, эффект выемки, скорость задержки, а также направление (1 – вверх, 0 – вниз).
У нас также будет указана скорость анимации фонового цвета, анимация пунктов меню, а также текста и фонового цвета, который указан в нашем коде CSS.
return this.each(function() {
// if options exist, lets merge them with our default settings
if ( options ) {
$.extend( settings, options );
}
var $el = $(this),
// the menu items
$menuItems = $el.children('li'),
// save max delay time for mouseleave anim parameters
maxdelay = Math.max( settings.animMouseleave['mText'].speed + settings.animMouseleave['mText'].delay ,
settings.animMouseleave['sText'].speed + settings.animMouseleave['sText'].delay ,
settings.animMouseleave['icon'].speed + settings.animMouseleave['icon'].delay
),
// timeout for the mouseenter event
// lets us move the mouse quickly over the items,
// without triggering the mouseenter event
t_mouseenter;
// save default top values for the moving elements:
// the elements that animate inside each menu item
$menuItems.find('.sti-item').each(function() {
var $el = $(this);
$el.data('deftop', $el.position().top);
});
// Events
...
});
Давайте создадим событие mouseenter для каждого пункта меню:
$menuItems.bind('mouseenter', function(e) {
clearTimeout(t_mouseenter);
var $item = $(this),
$wrapper = $item.children('a'),
wrapper_h = $wrapper.height(),
// the elements that animate inside this menu item
$movingItems= $wrapper.find('.sti-item'),
// the color that the texts will have on hover
hovercolor = $item.data('hovercolor');
t_mouseenter = setTimeout(function() {
// indicates the item is on hover state
$item.addClass('sti-current');
$movingItems.each(function(i) {
var $item = $(this),
item_sti_type = $item.data('type'),
speed = settings.animMouseenter[item_sti_type].speed,
easing = settings.animMouseenter[item_sti_type].easing,
delay = settings.animMouseenter[item_sti_type].delay,
dir = settings.animMouseenter[item_sti_type].dir,
// if dir is 1 the item moves downwards
// if -1 then upwards
style = {'top' : -dir * wrapper_h + 'px'};
if( item_sti_type === 'icon' ) {
// this sets another bg image position for the icon
style.backgroundPosition = 'bottom left';
} else {
style.color = hovercolor;
}
// we hide the icon, move it up or down, and then show it
$item.hide().css(style).show();
clearTimeout($item.data('time_anim'));
$item.data('time_anim',
setTimeout(function() {
// now animate each item to its default tops
// each item will animate with a delay specified
// in the options
$item.stop(true)
.animate({top : $item.data('deftop') + 'px'}, speed, easing);
}, delay)
);
});
// animate the bg color of the item
$wrapper.stop(true).animate({
backgroundColor: settings.defaultTextColor
}, settings.boxAnimSpeed );
}, 100);
})
А затем мы определим событие mouseleave, где всё будет в точности да наоборот:
// mouseleave event for each menu item
.bind('mouseleave', function(e) {
clearTimeout(t_mouseenter);
var $item = $(this),
$wrapper = $item.children('a'),
wrapper_h = $wrapper.height(),
$movingItems= $wrapper.find('.sti-item');
if(!$item.hasClass('sti-current'))
return false;
$item.removeClass('sti-current');
$movingItems.each(function(i) {
var $item = $(this),
item_sti_type = $item.data('type'),
speed = settings.animMouseleave[item_sti_type].speed,
easing = settings.animMouseleave[item_sti_type].easing,
delay = settings.animMouseleave[item_sti_type].delay,
dir = settings.animMouseleave[item_sti_type].dir;
clearTimeout($item.data('time_anim'));
setTimeout(function() {
$item.stop(true).animate({'top' : -dir * wrapper_h + 'px'}, speed, easing, function() {
if( delay + speed === maxdelay ) {
$wrapper.stop(true).animate({
backgroundColor: settings.defaultBgColor
}, settings.boxAnimSpeed );
$movingItems.each(function(i) {
var $el = $(this),
style = {'top' : $el.data('deftop') + 'px'};
if( $el.data('type') === 'icon' ) {
style.backgroundPosition = 'top left';
} else {
style.color = settings.defaultTextColor;
}
$el.hide().css(style).show();
});
}
});
}, delay);
});
});
И на этом всё! Надеемся, что вам понравилась эта статья, и она окажется полезной вам в вашем нелегком деле!
Смотреть демо | Скачать архивом
Внимание! У вас нет прав для просмотра скрытого текста.