[JS]これFlashじゃないの?ってなるナビゲーションを実装するjQueryのチュートリアル
Post on:2011年3月28日
軽快なアニメーションが心地よいナビゲーションを実装するjQueryのチュートリアルを紹介します。
タイトルにある通り、Flashは使わないで実装されてます。
Animated Content Menu with jQuery
デモページ
[ad#ad-2]
まずは、デモページを堪能ください。
ナビゲーションの各ラベルをクリックすると、それに対応したパネルがアニメーションを伴って開くようになっています。
実装
HTMLの構造は、背景画像、グリッドのオーバーレイ、ローディングのアイコン、メインメニューの4つから構成されています。
HTML:背景
背景は、背景画像とオーバーレイとローディングをdiv要素で内包します。
<div id="ac_background" class="ac_background"> <img class="ac_bgimage" src="images/Default.jpg" alt="Background"/> <div class="ac_overlay"></div> <div class="ac_loading"></div> </div>
HTML:メインメニュー
各アイテムはリスト要素で管理されており、パネルはdiv要素(ac_subitem)内に配置されています。
パネル内にはデモではリスト要素が配置されていますが、あらゆる要素を自由に配置することができます。
<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> </li> <li>...</li> <li>...</li> </ul> </div> </div>
[ad#ad-2]
JavaScript
「jquery.js」と「jquery.easing.1.3.js」を外部ファイルとし、下記のスクリプトを記述します。
$(function() { 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(); /* for this menu, we will preload all the images. let's add all the image sources to an array, including the bg image */ $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- loads the bg image and all the item images; 2- shows the bg image; 3- shows / slides out the menu; 4- shows the menu items; 5- initializes the menu items events */ $ac_loading.show();//show loading status image $.when(loadImages()).done(function(){ $.when(showBGImage()).done(function(){ //hide the loading status image $ac_loading.hide(); $.when(slideOutMenu()).done(function(){ $.when(toggleMenuItems('up')).done(function(){ initEventsSubMenu(); }); }); }); }); }, showBGImage = function() { return $.Deferred( function(dfd) { //adjusts the dimensions of the image to fit the screen adjustImageSize($ac_bgimage); $ac_bgimage.fadeIn(1000, dfd.resolve); } ).promise(); }, slideOutMenu = function() { /* calculate new width for the menu */ var new_w = $(window).width() - $title.outerWidth(true); return $.Deferred( function(dfd) { //slides out the menu $menu.stop() .animate({ width : new_w + 'px' }, 700, dfd.resolve); } ).promise(); }, /* shows / hides the menu items */ toggleMenuItems = function(dir) { return $.Deferred( function(dfd) { /* slides in / out the items. different animation time for each one. */ $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), // the <li> $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'); /* user clicks one item : appetizers | main course | desserts | wines | specials */ $el_title.bind('click.Menu', function(e) { $.when(toggleMenuItems('down')).done(function(){ openSubMenu($item, $sub_menu, el_image); }); return false; }); /* closes the submenu */ $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); }); }, /* changes the background image */ showItemImage = function(source) { //if its the current one return if($ac_bgimage.attr('src') === source) return false; var $itemImage = $('<img src="'+source+'" alt="Background" class="ac_bgimage"/>'); $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() { //show items toggleMenuItems('up'); }); }, /* on window resize, ajust the bg image dimentions, and recalculate the menus width */ initWindowEvent = function() { /* on window resize set the width for the menu */ $(window).bind('resize.Menu' , function(e) { adjustImageSize($ac_bgimage); /* calculate new width for the menu */ var new_w = $(window).width() - $title.outerWidth(true); $menu.css('width', new_w + 'px'); }); }, /* makes an image "fullscreen" and centered */ 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' }); }, /* preloads a set of images */ loadImages = function() { return $.Deferred( function(dfd) { var total_images = $ItemImages.length, loaded = 0; for(var i = 0; i < total_images; ++i){ $('<img/>').load(function() { ++loaded; if(loaded === total_images) dfd.resolve(); }).attr('src' , $ItemImages[i]); } } ).promise(); }; return { init : init }; })(); /* call the init method of Menu */ Menu.init(); });
CSS
デモのスタイルシートは「reset.css」を使用し、下記のようなります。
@import url('reset.css'); body{ background:#000; color:#fff; font-family: 'PT Sans Narrow', Arial, sans-serif; text-transform:uppercase; } a{ color:#fff; text-decoration:none; } img.ac_bgimage{ position:fixed; left:0px; top:0px; width:100%; 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; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px 10px 10px 10px; z-index:999; opacity:0.7; display:none; } .ac_content{ position:fixed; height:90px; width:100%; top:50%; left:0px; margin-top:-65px; } .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; } .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; } .ac_menu > ul > li{ float:left; position:relative; height:90px; overflow:hidden; } .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; } .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; } .ac_footer{ position:fixed; bottom:0px; left:0px; width:100%; font-size:13px; background:#000; opacity:0.9; height:20px; padding-bottom:5px; } .ac_footer a{ padding:5px 10px; letter-spacing:1px; text-shadow:1px 1px 1px #000; color:#ddd; float:right; } .footer a:hover{ color:#fff; } .ac_footer a span{ font-weight:bold; } .ac_footer a.ac_left{ float:left; }
sponsors