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

ایده از این قرار که عکس ها رو بصورت ستونی و سیاه سفید در کنار هم داریم ، که وقتی روی هر کدوم کلیک بشه عکس به صورت افقی ( کشویی ) باز خواهد شد و اطلاعات مربوط به اون شخص نمایش داده خواهد شد . همچنین عکس نفرات دیگه (grayed out) یا همون کم رنگ خودمون 😉 میشه .

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

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

ساختار اصلی HTML ما از یک Container اصلی تشکیل میشه که متشکل شده از لیستی که هر آیتم ، ستونی از اون رو تشکیل خواهد داد . به Container کلاس و آیدی با عنوان “ei_menu” خواهیم داد. هر آیتم از لیست دارای یک لینک و دو تگ Span و یک تگ Div برای محتوا می باشد . تگ های Span برای نشون دادن تصویر پس زمینه در ابتدای لودینگ قالب پروفایل مدیران می باشد و همچنین شامل تصویر رنگی که بعد از کلیک شدن نمایش داده خواهند شد .از اون جایی که برای هر آیتم عکس خاصی باید نشون داده بشه ، پس باید موقعیت تصویر پس زمینه رو جدا گونه تعریف کنیم . برای رسید به این مقصود از کلاس های “pos1” تا “pos5” که به لینک والدشون داده میشه استفاده میکنیم

<div id="ei_menu" class="ei_menu">
	<ul>
		<li>
			<a href="#" class="pos1">
				<span class="ei_preview"></span>
				<span class="ei_image"></span>
			</a>
			<div class="ei_descr">
				<h2>Gary</h2>
				<h3>Vocals</h3>
				<p>Some text here...</p>
			</div>
		</li>
		<li> ... </li>
	</ul>
</div>

به همین آسونی 😉 میریم سراغ استایل دهی.

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

عرض Container رو تمام صفحه میکنیم و همچنین Overflow رو hidden کردیم. 

.ei_menu{
	background:#111;
	width:100%;
	overflow:hidden;
}

اندازه ی مشخصی به تگ ul خواهیم داد که با Float کردن آیتم های لیست و کشویی شدنشون باعث نشه که بیوفتن خط بعد .

.ei_menu ul{
	height:350px;
	margin-left:50px;
	position:relative;
	display:block;
	width:1300px;
}

Overflow آیتم های لیست hidden خواهد شد . علت اینه که اطلاعات زیادی داخل هر آیتم هست که نباید در حالت عادی نمایش داده شود . و فقط وقتی که کلیک بشه با زیاد کردن عرض هر آیتم لیست ، اون ها رو نمایش خواهیم داد.

.ei_menu ul li{
	float:left;
	width:75px;
	height:350px;
	position:relative;
	overflow:hidden;
	border-right:2px solid #111;
}

تگ های Span ی که کلاس ei_preview دارند ، شامل عکس های سیاه و سفید هستند که Position اون ها Absolute خواهد بود.

.ei_preview{
	width:75px;
	height:350px;
	cursor:pointer;
	position:absolute;
	top:0px;
	left:0px;
	background:transparent url(../images/bw.jpg) no-repeat top left;
}

تگ های Span ی که کلاس ei_image دارند ، شامل عکس رنگی هستند که با انیمیت کردن به موقعیت خودشون خواهند برگشت و Opacity شون تعیین خواهد شد.

.ei_image{
	position:absolute;
	left:75px;
	top:0px;
	width:75px;
	height:350px;
	opacity:0.2;
	background:transparent url(../images/color.jpg) no-repeat top left;
}

برای تعیین موقعیت تصویر پس زمینه ، همانطور که اشاره شد کلاس هایی تعریف خواهد شد که به تگ لینک والدشون اطلاق میشه .

.pos1 span{
	background-position:0px 0px;
}
.pos2 span{
	background-position:-75px 0px;
}
.pos3 span{
	background-position:-152px 0px;
}
.pos4 span{
	background-position:-227px 0px;
}
.pos5 span{
	background-position:-302px 0px;
}
.pos6 span{
	background-position:-377px 0px;
}

تگ Div ی که حاوی محتوای هر تصویر است Position: Absolute خواهد داشت و مقدار Left اون قرار به اندازه ی عرض تگ Span تغییر بکنه .

.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;
}

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

.ei_descr h2{
	font-family: 'Rock Salt', arial, serif;
	font-size:26px;
	color:#333;
	padding:10px;
	text-shadow:0px 0px 1px #fff;
	background:#fff url(../images/stripe_light.gif) repeat top left;
}

همینطور استایلی برای تیتر های دوم :

.ei_descr h3{
	font-family: 'Raleway', arial, serif;
	color:#fff;
	text-shadow:0px 0px 1px #000;
	font-style:normal;
	padding:10px;
	background:#333;
}

در انتهای بخش استایل دهی با CSS ، استایل های مربوط به متن محتوا رو تعیین میکنیم .

.ei_descr p{
	color:#000;
	padding:10px 5px 0px 5px;
	line-height:18px;
	font-size:11px;
	font-family: Arial, sans-serif;
	text-transform:uppercase;
}

فقط ، Google Fonts فراموش نشه 🙂

<link href='https://fonts.googleapis.com/css?family=Rock+Salt' rel='stylesheet' type='text/css' />
<link href='https://fonts.googleapis.com/css?family=Raleway:100' rel='stylesheet' type='text/css' />

همونطور که می دونید دو خط فوق در بخش Head فایل HTML تون نوشته میشه .

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

قرار آیتم های هر منو رو بعد از کلیک شدن باز کنیم . یعنی قرار عرص هر Li آیتم رو به 400px انیمیت کنیم (مجموع عرض Span:75px و محتوا به عرض 325px با احتساب padding و border) ، همزمان تصویر رنگی رو باز خواهیم کرد و مقدار Opacity رو انیمت میکنیم. همچنین سایر تصاویر کم رنگ تر شده که باعث میشه حس یکی شدن با پس زمینه ی مشکی قالب رو به ما بده .

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

var $menu				= $('#ei_menu > ul'),
	$menuItems			= $menu.children('li'),
	$menuItemsImgWrapper= $menuItems.children('a'),
	$menuItemsPreview	= $menuItemsImgWrapper.children('.ei_preview'),
	totalMenuItems		= $menuItems.length,

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

ExpandingMenu 	= (function(){
	/*
		@current
		set it to the index of the element you want to be opened by default,
		or -1 if you want the menu to be closed initially
	 */
	var current				= -1,
	/*
		@anim
		if you want the default opened item to animate initially, set this to true
	 */
	anim				= true,
	/*
		checks if the current value is valid -
		between 0 and the number of items
	 */
	validCurrent		= function() {
		return (current >= 0 && current < totalMenuItems);
	},
	init				= function() {
			/* show default item if current is set to a valid index */
		if(validCurrent())
			configureMenu();
			
		initEventsHandler();
	},
	configureMenu		= function() {
			/* get the item for the current */
		var $item	= $menuItems.eq(current);
			/* if anim is true, slide out the item */
		if(anim)
			slideOutItem($item, true, 900, 'easeInQuint');
		else{
				/* if not, just show it */
			$item.css({width : '400px'})
			.find('.ei_image')
			.css({left:'0px', opacity:1});
					 
				/* decrease the opacity of the others */	
				$menuItems.not($item)
						  .children('.ei_preview')
						  .css({opacity:0.2});	 
		}
	},
	initEventsHandler	= function() {
			/*
			when we click an item the following can happen:
			1) The item is already opened - close it!
			2) The item is closed - open it! (if another one is opened, close that one!)
			*/
		$menuItemsImgWrapper.bind('click.ExpandingMenu', function(e) {
			var $this 	= $(this).parent(),
			idx		= $this.index();
				
			if(current === idx) {
				slideOutItem($menuItems.eq(current), false, 1500, 'easeOutQuint', true);
				current = -1;
			}
			else{
				if(validCurrent() && current !== idx)
						slideOutItem($menuItems.eq(current), false, 250, 'jswing');
					
				current	= idx;
					slideOutItem($this, true, 250, 'jswing');
			}
			return false;
		});
	},
		/* if you want to trigger the action to open a specific item */
		openItem			= function(idx) {
			$menuItemsImgWrapper.eq(idx).click();
		},
		/*
		opens or closes an item
		note that "mLeave" is just true when all the items close,
		in which case we want that all of them get opacity 1 again.
		"dir" tells us if we are opening or closing an item (true | false)
		*/
	slideOutItem		= function($item, dir, speed, easing, mLeave) {
		var $ei_image	= $item.find('.ei_image'),
				
		itemParam	= (dir) ? {width : '400px'} : {width : '75px'},
		imageParam	= (dir) ? {left : '0px'} : {left : '75px'};
			
			/*
			if opening, we animate the opacity of all the elements to 0.1.
			we do this in order to enhance the opened item more:
			*/
		if(dir)
		/*
				alternative:
				$menuItemsPreview.not($menuItemsPreview.eq(current))
								 .stop()
								 .animate({opacity:0.1}, 500);
		 */
			$menuItemsPreview.stop()
		.animate({opacity:0.1}, 1000);
		else if(mLeave)
			$menuItemsPreview.stop()
		.animate({opacity:1}, 1500);
			
			/* the <li> expands or collapses */
		$item.stop().animate(itemParam, speed, easing);
			/* the image span (color) slides in or out */
		$ei_image.stop().animate(imageParam, speed, easing, function() {
				/* 
				if opening, we animate the opacity to 1, 
				otherwise we reset it.
				*/
			if(dir)
				$ei_image.animate({opacity:1}, 2000);
			else
				$ei_image.css('opacity', 0.2);
		});
	};
		
	return {
		init 		: init,
		openItem	: openItem
	};
})();
	
/*
call the init method of ExpandingMenu
 */
ExpandingMenu.init();

/*
if you want to open / close a specific item you could do it like this:
ExpandingMenu.openItem(3); // toggles item 3 (zero-based indexing)
*/

و تمام . امیدوارم لذت برده باشید 😉