jQuery: слайдер с эффектом параллакса

Have a question? Ask in chat with AI!

Parallax SliderДоброго времени суток! Сегодня мы будем создавать слайдер с использованием некоторых принципов эффекта параллакса. Я уже писал о плагине Scrolling Parallax совсем недавно. Там мы использовали плагин, а тут напишем все с нуля. Итак, приступим к созданию слайдера с эффектом параллакса на jQuery.

[adsense]
Посмотреть демоСкачать исходники

 

Parallax Slider

Разметка

HTML структура будет содержать главный контейнер с классом pxs_container. Добавим так же слой, который будет содержать три разных фоновых изображения. Мы будем анимировать эти изображения по-разному дабы создать эффект параллакса. Фоновые изображения будут немного прозрачны, дабы в итоге получить наложение их друг на друга. Мы так же добавим элемент, который будет показываться при загрузке слайдера и два списка для миниатюр и полноразмерных изображений.


 

 

 

Loading images…

 

    • First Image

 

  • Second Image

 

 

 

    • First Image

 

  • Second Image

 

Теперь посмотрим в сторону CSS стилей.

CSS

Начнем мы пожалуй с главного контейнера. Так как мы будем использовать всю ширину страницы для нашего слайдера, мы установим ширину в 100%. Свойство position мы установим в значение relative, т.к. у нас внутри контейнера будут элементы с абсолютным позиционированием.

.pxs_container{
	width:100%;
	height:420px;
	position:relative;
	border-top:7px solid #333;
	border-bottom:7px solid #333;
	overflow:hidden;
	-moz-box-shadow:0px 0px 7px #000;
	-webkit-box-shadow:0px 0px 7px #000;
	box-shadow:0px 0px 7px #000;
}

Контейнер, в котором будут содержаться фоновые изображения будет иметь повторяющийся фон, который по сути есть обычный градиент.

.pxs_bg{
	background:transparent url(../images/bg.png) repeat top left;
}

Зададим общие свойства для блоков внутри этого контейнера:

.pxs_bg div{
	position:absolute;
	top:0px;
	left:0px;
	height:420px;
	background-repeat:repeat;
	background-position:top left;
	background-color:transparent;
}

Ширина будет устанавливаться динамически с помощью JavaScript. Отдельные блоки div будут содержать в качестве фона разные фоновые изображения.

.pxs_bg .pxs_bg1{
	background-image:url(../images/bg1.png);
}
.pxs_bg .pxs_bg2{
	background-image:url(../images/bg2.png);
}
.pxs_bg .pxs_bg3{
	background-image:url(../images/bg3.png);
}

Мы так же будем устанавливать динамически левую границу этих блоков с помощью JS, но вернемся к этому чуть позже. Давайте разберемся с CSS стилями остальных элементов.
При первоначальной загрузке наш контейнер pxs_slider_wrapper будет невидим:

.pxs_slider_wrapper{
	display:none;
}

Так как этот контейнер содержит все элементы, которые мы грузим вначале, то мы будем его показывать только после того, как все нужные нам элементы загрузятся.

Давайте сбросим стили для обоих списков:

.pxs_container ul{
	margin:0px;
	padding:0px;
	list-style:none;
}

Идея списков в слайдере состоит в том, что мы делаем очень длинный список во всю ширину окна. То, что вы видите в окне браузера на самом деле есть элемент списка. Мы будем устанавливать ширину списка ul динамически и она будет в несколько раз больше ширины окна, чтобы туда уместились все наши изображения.

ul.pxs_slider{
	position:absolute;
	left:0px;
	top:0px;
	height:420px;
}
ul.pxs_slider li{
	height:420px;
	float:left;
	position:relative;
}

Изображение внутри слайдера будет расположено горизонтально по центру. Сделаем мы это с помощью свойства margin выставив значение левого и правого отступов в значение auto.

ul.pxs_slider li img{
	display:block;
	margin:35px auto 0px auto;
	-moz-box-shadow:0px 0px 7px #222;
	-webkit-box-shadow:0px 0px 7px #222;
	box-shadow:0px 0px 7px #222;
	border: 8px solid transparent;
	-moz-border-radius:4px;
	-webkit-border-radius:4px;
	border-radius:4px;
}

Добавив прозрачную границу и использовав свойство box-shadow мы создадим эффект зеркальной рамки вокруг изображения.

Список с миниатюрами изображений мы будем позиционировать так же абсолютно. Мы добавим отступ слева 50% для того, чтобы центрировать список. Чтобы окончательно отцентрировать список мы установим динамически ширину всего списка и свойство margin-left в отрицательное значение, равное половине от общей ширины.

ul.pxs_thumbnails{
	height:35px;
	position:absolute;
	top:320px;
	left:50%;
}
ul.pxs_thumbnails li{
	position:absolute;
	display:block;
}

Далее мы оформим миниатюры, добавив им границу белого цвета и немного сыграем с помощью свойства box-shadow:

ul.pxs_thumbnails li img{
	border: 5px solid #FFFFFF;
	-moz-box-shadow:1px 1px 7px #555;
	-webkit-box-shadow:1px 1px 7px #555;
	box-shadow:1px 1px 7px #555;
	cursor:pointer;
	display:block;
	opacity:0.7;
}

Миниатюра текущего изображения должна быть полностью непрозрачна:

ul.pxs_thumbnails li.selected img{
	opacity:1.0;
}

Общие стили для элементов навигации будут такими:

.pxs_navigation span{
	position:absolute;
	width:30px;
	height:60px;
	-moz-box-shadow:0px 0px 2px #000;
	-webkit-box-shadow:0px 0px 2px #000;
	box-shadow:0px 0px 2px #000;
	top:145px;
	opacity:0.6;
	-moz-border-radius:4px;
	-webkit-border-radius:4px;
	border-radius:4px;
	cursor:pointer;
}
.pxs_navigation span:hover{
	opacity:0.9;
}

ну и добавим изображения стрелок для элементов навигации:

.pxs_navigation span.pxs_prev{
	background:#000 url(../images/prev.png) no-repeat center center;
}
.pxs_navigation span.pxs_next{
	background:#000 url(../images/next.png) no-repeat center center;
}

Левая и правая позиции для наших элементов навигации мы будем задавать динамически для того, чтобы они были прилеплены к нашему основному изображению.

Последнее, что нам нужно сделать — это задать стили для элемента загрузки — он будет показываться пока наши изображения подгружаются.

.pxs_loading{
	color:#fff;
	font-size:20px;
	padding:15px 15px 15px 50px;
	position:absolute;
	background:#333 url(../images/ajax-loader.gif) no-repeat 10px 50%;
	-moz-border-radius:15px;
	-webkit-border-radius:15px;
	border-radius:15px;
	opacity:0.7;
	width:180px;
	position:absolute;
	top:150px;
	left:50%;
	margin-left:-90px;
}

На этом со стилями CSS мы закончили. Осталось разобраться с JavaScript.

JavaScript

Основная идея слайдера состоит в том, чтобы прокручивать изображения и анимировать три фоновых изображения таким образом, чтобы создавался эффект параллакса. При смене слайда мы будем смещать фоновое изображение, которое находиться ближе к нам на половину ширины экрана. Следующее за ним фоновое изображение мы сдвинем лишь на четверть ширины экрана и т.д. Все это создаст нужный нам эффект параллакса.
Далее будет много JavaScript кода — его можно вынести в отдельный файл:

(function($) {
	$.fn.parallaxSlider = function(options) {
		var opts = $.extend({}, $.fn.parallaxSlider.defaults, options);
		return this.each(function() {
			var $pxs_container 	= $(this),
			o 				= $.meta ? $.extend({}, opts, $pxs_container.data()) : opts;

			//the main slider
			var $pxs_slider		= $('.pxs_slider',$pxs_container),
			//the elements in the slider
			$elems			= $pxs_slider.children(),
			//total number of elements
			total_elems		= $elems.length,
			//the navigation buttons
			$pxs_next		= $('.pxs_next',$pxs_container),
			$pxs_prev		= $('.pxs_prev',$pxs_container),
			//the bg images
			$pxs_bg1		= $('.pxs_bg1',$pxs_container),
			$pxs_bg2		= $('.pxs_bg2',$pxs_container),
			$pxs_bg3		= $('.pxs_bg3',$pxs_container),
			//current image
			current			= 0,
			//the thumbs container
			$pxs_thumbnails = $('.pxs_thumbnails',$pxs_container),
			//the thumbs
			$thumbs			= $pxs_thumbnails.children(),
			//the interval for the autoplay mode
			slideshow,
			//the loading image
			$pxs_loading	= $('.pxs_loading',$pxs_container),
			$pxs_slider_wrapper = $('.pxs_slider_wrapper',$pxs_container);

			//first, preload all the images
			var loaded		= 0,
			$images		= $pxs_slider_wrapper.find('img');

			$images.each(function(){
				var $img	= $(this);
				$('').load(function(){
					++loaded;
					if(loaded	== total_elems*2){
						$pxs_loading.hide();
						$pxs_slider_wrapper.show();

						//width of an image
						//(assuming all images have the same sizes)
						var one_image_w		= $pxs_slider.find('img:first').width();

						/*
						set the width of the slider,
						of each one of its elements, and of the
						navigation buttons
						 */
						setWidths($pxs_slider,
						$elems,
						total_elems,
						$pxs_bg1,
						$pxs_bg2,
						$pxs_bg3,
						one_image_w,
						$pxs_next,
						$pxs_prev);

						/*
						set the widths of the thumbs
						and spread them evenly
						 */
						$pxs_thumbnails.css({
							'width'			: one_image_w + 'px',
							'margin-left' 	: -one_image_w/2 + 'px'
						});
						var spaces	= one_image_w/(total_elems+1);
						$thumbs.each(function(i){
							var $this 	= $(this);
							var left	= spaces*(i+1) - $this.width()/2;
							$this.css('left',left+'px');

							if(o.thumbRotation){
								var angle 	= Math.floor(Math.random()*41)-20;
								$this.css({
									'-moz-transform'	: 'rotate('+ angle +'deg)',
									'-webkit-transform'	: 'rotate('+ angle +'deg)',
									'transform'			: 'rotate('+ angle +'deg)'
								});
							}
							//hovering the thumbs animates them up and down
							$this.bind('mouseenter',function(){
								$(this).stop().animate({top:'-10px'},100);
							}).bind('mouseleave',function(){
								$(this).stop().animate({top:'0px'},100);
							});
						});

						//make the first thumb to be selected
						highlight($thumbs.eq(0));

						//slide, when clicking the navigation buttons
						$pxs_next.bind('click',function(){
							++current;
							if(current >= total_elems)
								if(o.circular)
									current = 0;
							else{
								--current;
								return false;
							}
							highlight($thumbs.eq(current));
							slide(current,
							$pxs_slider,
							$pxs_bg3,
							$pxs_bg2,
							$pxs_bg1,
							o.speed,
							o.easing,
							o.easingBg);
						});
						$pxs_prev.bind('click',function(){
							--current;
							if(current < 0)
								if(o.circular)
									current = total_elems - 1;
							else{
								++current;
								return false;
							}
							highlight($thumbs.eq(current));
							slide(current,
							$pxs_slider,
							$pxs_bg3,
							$pxs_bg2,
							$pxs_bg1,
							o.speed,
							o.easing,
							o.easingBg);
						});

						/*
						clicking a thumb will slide to the respective image
						 */
						$thumbs.bind('click',function(){
							var $thumb	= $(this);
							highlight($thumb);
							//if autoplay interrupt when user clicks
							if(o.auto)
								clearInterval(slideshow);
							current 	= $thumb.index();
							slide(current,
							$pxs_slider,
							$pxs_bg3,
							$pxs_bg2,
							$pxs_bg1,
							o.speed,
							o.easing,
							o.easingBg);
						});

						/*
						activate the autoplay mode if
						that option was specified
						 */
						if(o.auto != 0){
							o.circular	= true;
							slideshow	= setInterval(function(){
								$pxs_next.trigger('click');
							},o.auto);
						}

						/*
						when resizing the window,
						we need to recalculate the widths of the
						slider elements, based on the new window width;
						we need to slide again to the current one,
						since the left of the slider is no longer correct
						 */
						$(window).resize(function(){
							w_w	= $(window).width();
							setWidths(
								$pxs_slider,
								$elems,
								total_elems,
								$pxs_bg1,
								$pxs_bg2,
								$pxs_bg3,
								one_image_w,
								$pxs_next,
								$pxs_prev
								);
							slide(
								current,
								$pxs_slider,
								$pxs_bg3,
								$pxs_bg2,
								$pxs_bg1,
								1,
								o.easing,
								o.easingBg
								);
						});

					}
				}).error(function(){
					alert('here')
				}).attr('src',$img.attr('src'));
			});
		});
	};

	//the current window width
	var w_w				= $(window).width();

	var slide			= function(current,
	$pxs_slider,
	$pxs_bg3,
	$pxs_bg2,
	$pxs_bg1,
	speed,
	easing,
	easingBg){
		var slide_to	= parseInt(-w_w * current);
		$pxs_slider.stop().animate({
			left	: slide_to + 'px'
		},speed, easing);
		$pxs_bg3.stop().animate({
			left	: slide_to/2 + 'px'
		},speed, easingBg);
		$pxs_bg2.stop().animate({
			left	: slide_to/4 + 'px'
		},speed, easingBg);
		$pxs_bg1.stop().animate({
			left	: slide_to/8 + 'px'
		},speed, easingBg);
	}

	var highlight		= function($elem){
		$elem.siblings().removeClass('selected');
		$elem.addClass('selected');
	}

	var setWidths		= function($pxs_slider,
	$elems,
	total_elems,
	$pxs_bg1,
	$pxs_bg2,
	$pxs_bg3,
	one_image_w,
	$pxs_next,
	$pxs_prev){
		/*
		the width of the slider is the window width
		times the total number of elements in the slider
		 */
		var pxs_slider_w	= w_w * total_elems;
		$pxs_slider.width(pxs_slider_w + 'px');
		//each element will have a width = windows width
		$elems.width(w_w + 'px');
		/*
		we also set the width of each bg image div.
		The value is the same calculated for the pxs_slider
		 */
		$pxs_bg1.width(pxs_slider_w + 'px');
		$pxs_bg2.width(pxs_slider_w + 'px');
		$pxs_bg3.width(pxs_slider_w + 'px');

		/*
		both, the right and left of the
		navigation next and previous buttons will be:
		windowWidth/2 - imgWidth/2 + some margin
		(not to touch the image borders)
		 */
		var position_nav	= w_w/2 - one_image_w/2 + 3;
		$pxs_next.css('right', position_nav + 'px');
		$pxs_prev.css('left', position_nav + 'px');
	}

	$.fn.parallaxSlider.defaults = {
		auto			: 0,
		speed			: 1000,
		easing			: 'jswing',
		easingBg		: 'jswing',
		circular		: true,
		thumbRotation	: true
	};
	//easeInOutExpo,easeInBack
})(jQuery);

Для активации нашего слайдера следует добавить следующий код:

$(function() {
	var $pxs_container	= $('#pxs_container');
	$pxs_container.parallaxSlider();
});

Опции для слайдера будут такие:

  • auto: можно задать время в секундах, через которое слайды будут автоматически сменяться. Если установить в 0 тогда автосмены слайдов не будет.
  • speed: скорость анимации каждого слайда
  • easing: эффект easing для анимации слайдов
  • easingBg: эффект easing для анимации фоновых изображений
  • circular: зацикливание слайдера
  • thumbRotation: дает возможность перемешать миниатюры

На этом собственно и все. Если текст вам кажется сложным — просто скачайте исходники и разобраться станет легче.
Посмотреть демоСкачать исходники

Если вы житель Челябинска или Челябинской области вам будет полезен сайт mebel74.ru, где вы сможете подобрать лучшую мебель по лучшей цене и уточнить наличие в магазинах города.


2 комментария для “0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Предыдущая запись 9 вещей, которые стоит сделать после установки WordPress
Следующая запись CSS3 кнопки. 4 варианта анимированных кнопок