[JS]これFlashじゃないの?ってなるナビゲーションを実装するjQueryのチュートリアル

軽快なアニメーションが心地よいナビゲーションを実装する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

top of page

©2018 coliss