امروز قصد داریم قالب یک سایت معرفی شخصی و نمونه کارها رو (Portfolio WebSite) با انیمیشن های تمیز با استفاده از کتابخونه ی جاوااسکریپتی JQuery با هم طراحی کنیم . ایده از این قراره که چندتا جعبه ی کوچیک رو به صورت پراکنده و درهم رو تو پس زمینه داشته باشیم. وقتی روی هر آیتم از منو کلیک میشه جعبه ها ی پراکنده یکجا جمع بشن و تشکیل یه جعبه ی بزرگ رو بدن که محتوا رو درش نمایش بدیم.

برای جعبه های محتوا با استفاده از کتابخونه ی  jScrollPane Plugin اسکرول بار مخصوصی (Customize scroll bar) متفاوت از اسکرول مرورگر درست خواهیم کرد.

همچنین برای انیمیت های چرخوندن (Rotate) کردن جعبه ها از  jQuery 2d transformation plugin  و برای انیمیت های Easing از  jQuery Easing Plugin استفاده خواهیم کرد.

عکس ها توسط Jin گرفته شده که میتونید پروفایل Flikr شون رو ببینید.

با کدهای HTML شروع میکنیم

در ابتدا تصویر پس زمینه اولیه را با یک افکت ریز اجرا میکنیم.

<div id="mb_background" class="mb_background">
	<img class="mb_bgimage" src="images/default.jpg" alt="Background"/>
	<div class="mb_overlay"></div>
</div>

Div بعدی رو برای قرار دادن جعبه های کوچیک با موقعیت های رندوم و درجه چرخش های مختلف ایجاد میکنیم.

<div id="mb_pattern" class="mb_pattern"></div>

16 جعبه رو داخل این Div قرار خواهیم داد.

منو و تیتر ساختار زیر رو دارند.

<div class="mb_heading">
	<h1>Lack of Color</h1>
</div>

<div id="mb_menu" class="mb_menu">
	<a href="#" data-speed="600" data-easing="easeOutBack">About</a>
	<a href="#" data-speed="1000" data-easing="easeInExpo">Work</a>
	<a href="#" data-speed="600" data-easing="easeOutBack">Media</a>
	<a href="#" data-speed="1000" data-easing="easeInExpo">Contact</a>
</div>

همونطور که می بینید ، دو خصوصویت “-data” رو به لینک ها اضافه کردیم که سرعت و نحوه ی انیمت کردن جعبه هارو برای هر آیتم جداگانه تعریف میکنه. درباره ی خصوصیت data در HTML بخونید.

بعد، ساختار محتوای مورد نمایش رو تعیین میکنیم . یه Div والد با کلاس “mb_content_wrapper” تعریف میکنیم . که شامل ساختار محتوا و آیکون بستن محتوا خواهد بود.

<div id="mb_content_wrapper" class="mb_content_wrapper">
	<span class="mb_close"></span>
	<div class="mb_content">
		<h2>About</h2>
		<div class="mb_content_inner">
			<p>Some text...</p>
		</div>
	</div>
	<div class="mb_content">
		...
	</div>
	<div class="mb_content">
		...
	</div>
	<div class="mb_content">
		...
	</div>
</div>

داخل یکی از تب های محتوا قرار است که تصاویری رو نشون بدیم که میتونه نمونه کار ها قرار بگیره.

<div class="mb_content_inner">
	<p>...</p>
	<ul id="mb_imagelist" class="mb_imagelist">
		<li><img src="images/small/1.jpg" alt="image1" data-bgimg="images/image1.jpg"/></li>
		<li><img src="images/small/2.jpg" alt="image2" data-bgimg="images/image2.jpg"/></li>
		<li>...</li>
	</ul>
	<p>...</p>
</div>

برای استایل دهی از بخش زیر شروع میکنیم

استایل دهی با CSS

در ابتدا فایل Rest.css (مقادیر اولیه ی CSS ) رو درش معرفی کردیم و استایل های اولیه رو تعریف میکنیم.

@import url('reset.css');

body{
	background:#000;
	color:#fff;
	font-family: 'PT Sans Narrow', Arial, sans-serif;
}
a{
	color:#fff;
	text-decoration:none;
}

در این مرحله ، استایل های تصویر پس زمینه و افکتی که قرار روی تصویر رو بپوشونه رو تنظیم می کنیم. 

img.mb_bgimage{
	position:fixed;
	left:0px;
	top:0px;
	width:100%;
	opacity:0.8;
	z-index:1;
}
.mb_overlay{
	width:100%;
	height:100%;
	position:fixed;
	top:0px;
	left:0px;
	background:transparent url(../images/pattern.png) repeat top left;
	z-index:2;
}

هر دو المان Position: fixed تعریف شدند و با z-index پایینی مطمعن میشیم که زیر همه ی المان ها قرار میگیرند.

جعبه های کوچیک رو با ارتفاع و عرض 50px و Position:Absolute مشخص میکنیم.

.mb_pattern div{
	position:absolute;
	width:50px;
	height:50px;
	background:#000;
	z-index:10;
}

تیتر محتوا نیز Position:Absolute  خواهد داشت و از فونت های گوگل استفاده خواهیم کرد.

.mb_heading h1{
	position:absolute;
	top:10px;
	left:10px;
	font-size:86px;
	color:#000;
	text-shadow:0px 0px 1px #fff;
	font-family:"Astloch", Arial, sans-serif;
	z-index:4;
}

منو در سمت چپ صفحه قرار دارد.

.mb_menu{
	position:absolute;
	top:154px;
	left:0px;
	z-index:11;
}

لینک های داخل منو :

.mb_menu a{
	background-color:#000;
	margin-bottom:2px;
	opacity:0.9;
	display:block;
	width:98px;
	height:98px;
	color:#fff;
	line-height:98px;
	text-align:center;
	text-transform:uppercase;
	outline:none;
	-webkit-transition: all 0.2s ease-in;
	-moz-transition:all 0.2s ease-in;
	-o-transition: all 0.2s ease-in;
	-transition: all 0.2s ease-in;
}
.mb_menu a:hover{
	color:#000;
	background-color:#fff;
}

راجع به transition میتونین از https://www.w3.org/TR/css3-transitions/ یا Understanding CSS3 Transitions اطلاعات بیشتری کسب کنید.

محتوا رو قرار نیست در ابتدا نمایش دهیم. پس:

.mb_content_wrapper{
	background:transparent url(../images/bg_menu.png) repeat top left;
	width:400px;
	height:400px;
	position:absolute;
	top:154px;
	left:200px;
	z-index:4;
	display:none;
}

چرا از Opacity برای تعیین شفافیت استفاده نکردیم ؟ و به جاش از یک تصویر پس زمینه ی تکرار شونده استفاده کردیم ؟

دلیل این کار این هست که بعضی از مرورگر ها وقتی به یک والدی Opacity تعلق میگیره ، این میزان شفافیت رو برای فرزندان اش هم استفاده میکنن. که باعث میشه المان های داخلی به صورت صحییح نمایش داده نشن 😉

آیکون بستن :

span.mb_close{
	position:absolute;
	top:10px;
	right:10px;
	width:11px;
	height:12px;
	cursor:pointer;
	background:transparent url(../images/close.png) no-repeat top left;
	opacity:0.8;
}
span.mb_close:hover{
	opacity:1.0;
}

محتوای داخلی دارای Padding و در حالت اولیه نمایش داده نمی شود.

.mb_content{
	padding:30px;
	display:none;
}

تیتر محتوا و خطی که زیرش خواهیم انداخت.

.mb_content h2{
	font-family:"Astloch";
	text-shadow:0px 0px 1px #fff;
	font-size:42px;
	background:transparent url(../images/line.png) repeat-x bottom left;
	padding:0px 0px 5px 0px;
	margin-bottom:10px;
}

برای اسکرولی که اضافه کردیم و متن محتوای داخلی.

.mb_content_inner{
	line-height:24px;
	height:268px;
	outline: none;
}
.mb_content_inner p{
	padding:5px 0px;
}

برای تصاویر نمونه کار ها :

ul.mb_imagelist li{
	float:left;
	margin:2px;
	cursor:pointer;
}
ul.mb_imagelist li img{
	display:block;
	opacity:0.3;
	-webkit-transition: all 0.5s ease-in-out;
	-moz-transition: all 0.5s ease-in-out;
	-o-transition: all 0.5s ease-in-out;
	-transition: all 0.5s ease-in-out;
}
ul.mb_imagelist li img:hover{
	opacity:1.0;
}

همونطور که مشاهده می کنید transition ی برای رفتن موس روی عکس ها (Hover) مشخص کردیم.

استایل دهی به پایان رسید . میریم سراغ JQuery 😉

شروع به نوشتن JavaScript می کنیم.

بعضی از المان ها رو کش میکنیم.

var $menu				= $('#mb_menu'),
	$menuItems			= $menu.children('a'),
	$mbWrapper			= $('#mb_content_wrapper'),
	$mbClose			= $mbWrapper.children('.mb_close'),
	$mbContentItems		= $mbWrapper.children('.mb_content'),
	$mbContentInnerItems= $mbContentItems.children('.mb_content_inner');
	$mbPattern			= $('#mb_pattern'),
	$works				= $('#mb_imagelist > li'),
	$mb_bgimage			= $('#mb_background > img'),

تابع مربوط به منو رو تعریف میکنیم.

Menu		 		= (function(){
  ...
})();

/*
call the init method of Menu
 */
Menu.init();

تابع اصلیمون رو داخل تابع منو تعریف کردیم و راه اندازی اولیه رو مشخص کردیم.

var init			= function() {
	preloadImages();
	initPlugins();
	initPattern();
	initEventsHandler();
},

تصاویر مربوط به نمونه کار هارو به صورت اولیه لود میکنیم.

preloadImages		= function() {
	$works.each(function(i) {
		$('').attr('src' , $(this).children('img').data('bgimg'));
	});
},

پلاگین jScollPane رو راه اندازی میکنیم و به جای اسکرول اصلی تعیین اش میکنیم.

initPlugins			= function() {
	$mbContentInnerItems.jScrollPane({
		verticalDragMinHeight: 40,
		verticalDragMaxHeight: 40
	});
},

جعبه های کوچک رو به صورت رندوم در منطقه ی مشخص شده ایجاد میکنیم.

initPattern			= function() {
	for(var i = 0; i < 16 ; ++i) {
		//opacity, random top, left and angle
		var o		= 0.1,
		t		= Math.floor(Math.random()*196) + 5, // between 5 and 200
		l		= Math.floor(Math.random()*696) + 5, // between 5 and 700
		a		= Math.floor(Math.random()*101) - 50; // between -50 and 50
				
		$el		= $('

').css({ opacity : o, top : t + 'px', left : l + 'px' }); if (!$.browser.msie) $el.transform({'rotate' : a + 'deg'}); $el.appendTo($mbPattern); } $mbPattern.children().draggable(); //just for fun },

بعد از کلیک کردن روی آیکون بستن ، جعبه ها باز به صورت رندوم چیده خواهند شد.

disperse			= function() {
	$mbPattern.children().each(function(i) {
		var o			= 0.1,
		t			= Math.floor(Math.random()*196) + 5, 
		l			= Math.floor(Math.random()*696) + 5, 
		a			= Math.floor(Math.random()*101) - 50; 
		$el			= $(this),
		param		= {
			width	: '50px',
			height	: '50px',
			opacity	: o,
			top		: t + 'px',
			left	: l + 'px'
		};
				
		if (!$.browser.msie)
			param.rotate	= a + 'deg';
				
		$el.animate(param, 1000, 'easeOutExpo');
	});
},

روی دادهایی مثل کلیک رو تعریف میکنیم.

initEventsHandler		= function() {
	/*
		click a link in the menu
	 */
	$menuItems.bind('click', function(e) {
		var $this	= $(this),
		pos		= $this.index(),
		speed	= $this.data('speed'),
		easing	= $this.data('easing');
		//if an item is not yet shown
		if(!$menu.data('open')){
			//if current animating return
			if($menu.data('moving')) return false;
			$menu.data('moving', true);
			$.when(openItem(pos, speed, easing)).done(function(){
				$menu.data({
					open	: true,
					moving	: false
				});
				showContentItem(pos);
				$mbPattern.children().fadeOut(500);
			});
		}
		else
			showContentItem(pos);
		return false;
	});
		
	/*
		click close makes the boxes animate to the top of the page
	 */
	$mbClose.bind('click', function(e) {
		$menu.data('open', false);
		/*
			if we would want to show the default image when we close:
			changeBGImage('images/default.jpg');
		 */
		$mbPattern.children().fadeIn(500, function() {
			$mbContentItems.hide();
			$mbWrapper.hide();
		});
			
		disperse();
		return false;
	});
		
	/*
		click an image from "Works" content item,
		displays the image on the background
	 */
	$works.bind('click', function(e) {
		var source	= $(this).children('img').data('bgimg');
		changeBGImage(source);
		return false;
	});
			
},

برای تغییر تصویر پس زمینه به نمونه کاری که توسط کاربر کلیک شده :

changeBGImage			= function(img) {
	//if its the current one return
	if($mb_bgimage.attr('src') === img || $mb_bgimage.siblings('img').length > 0)
		return false;
				
	var $itemImage = $('<img src="'+img+'" alt="Background" class="mb_bgimage" style="display:none;"/>');
	$itemImage.insertBefore($mb_bgimage);
		
	$mb_bgimage.fadeOut(1000, function() {
		$(this).remove();
		$mb_bgimage = $itemImage;
	});
	$itemImage.fadeIn(1000);
},

عوض کردن محتوای جاری به محتوای دیگه.

showContentItem			= function(pos) {
	$mbContentItems.hide();
	$mbWrapper.show();
	$mbContentItems.eq(pos).show().children('.mb_content_inner').jScrollPane();
},

“openItem” برای تبدیل جعبه های کوچک به محیطی که محتوا درش نمایش داده بشه.

openItem				= function(pos, speed, easing) {
	return $.Deferred(
		function(dfd) {
			$mbPattern.children().each(function(i) {
				var $el			= $(this),
				param		= {
					width	: '100px',
					height	: '100px',
					top		: 154 + 100 * Math.floor(i/4),
					left	: 200 + 100 * (i%4),
					opacity	: 1
				};

				if (!$.browser.msie)
					param.rotate	= '0deg';

				$el.animate(param, speed, easing, dfd.resolve);
			});
		}
	).promise();
};

JQuery هم به پایان رسید . امیدواریم از قالب تک صفحه ایی زیبایی که برای معرفی شخصی و نمونه کارها (Portfolio WebSite) طراحی کردیم لذت ببرید.