jquery 图像滑块_三面板图像滑块

本文档介绍了如何使用jQuery和CSS3D变换创建一个响应式的三面板图像滑块,具有3D视觉效果。滑块由一个主面板和两个侧边面板组成,当导航时,面板会进行平滑的3D旋转过渡。教程详细阐述了HTML结构、CSS样式和JavaScript实现,包括过渡效果、阴影、悬停效果以及导航按钮的交互。
摘要由CSDN通过智能技术生成
jquery 图像滑块

jquery 图像滑块

Triple Panel Image Slider

In this tutorial we will create a jQuery triple panel image slider with a 3D look. The idea is to have a main panel and two lateral panels that are rotated slightly in 3D space. When navigating, we will slide in the respective next image in each panel. We’ll be using CSS 3D Transforms with perspective and CSS Transitions.

在本教程中,我们将创建具有3D外观的jQuery三面板图像滑块。 这个想法是要有一个主面板和两个在3D空间中稍微旋转的侧面板。 导航时,我们将在每个面板中滑动相应的下一张图像。 我们将结合透视图和CSS过渡使用CSS 3D变换。

The beautiful food images in the demo are by geishaboy500 and they are licensed under Creative Commons Attribution 2.0 Generic (CC BY 2.0).

演示中的精美食物图片由geishaboy500提供,并已根据知识共享署名2.0通用(CC BY 2.0)许可。

Please note: the result of this tutorial will only work as intended in browsers that support the respective CSS properties. 请注意:本教程的结果只能在支持各自CSS属性的浏览器中按预期工作。

We will omit vendor prefixes in this tutorial. But you’ll of course find them in the files.

在本教程中,我们将省略供应商前缀。 但是,您当然会在文件中找到它们。

Let’s get started!

让我们开始吧!

标记 (The Markup)

The initial structure that we’ll create will consist of a division with figures. Each figure will contain an image and a figcaption with the title and description for the image:

我们将创建的初始结构将包括数字分隔。 每个图将包含一个图像和一个说明标题,并带有该图像的标题和说明:

<div class="fs-slider" id="fs-slider">

	<figure>
		<img src="images/1.jpg" alt="image01" />
		<figcaption>
			<h3>Eloquence</h3>
			<p>American apparel flexitarian put a bird on it, mixtape typewriter irony aesthetic. </p>
		</figcaption>
	</figure>

	<figure>
		<img src="images/2.jpg" alt="image02" />
		<figcaption>
			<h3>Quintessential</h3>
			<p>Cardigan craft beer mixtape, skateboard forage fixie truffaut messenger bag. </p>
		</figcaption>
	</figure>

	<!-- ... -->

</div>

We will want our jQuery plugin to transform that structure into the following one:

我们将希望我们的jQuery插件将该结构转换为以下结构:

<section class="fs-container">

	<div class="fs-wrapper">

		<div class="fs-slider" id="fs-slider">

			<div class="fs-block">

				<figure style="display: block; ">
					<img src="images/1.jpg" alt="image01" />
					<figcaption>
						<h3>Eloquence</h3>
						<p>American apparel flexitarian put a bird on it, mixtape typewriter irony aesthetic. </p>
					</figcaption>
				</figure>

			</div><!-- /fs-block -->

			<div class="fs-block">
				<!-- ... -->
			</div>

			<!-- ... -->

		</div><!-- /fs-slider -->

		<nav class="fs-navigation">
			<span>Previous</span>
			<span>Next</span>
		</nav>

	</div><!-- /fs-wrapper -->

</section><!-- /fs-container -->

Each figure will be wrapped into a division with the class fs-block and we’ll add a navigation to the whole thing.

每个图都将被fs-block类包装成一个分区,并且我们将在整个过程中添加一个导航。

Let’s look at the style.

让我们看一下样式。

CSS (The CSS)

Since we want the image slider to be responsive, we will give it a percentage width. But we’ll also define a minimal and maximum width so that it doesn’t squeeze too much or grow out of proportion. We will add some paddings to the side because our blocks will be positioned using the CSS translate property (they will all be in the middle) and that will not affect the width of the element:

由于我们希望图像滑块具有响应性,因此我们给它一个百分比宽度。 但是,我们还将定义最小和最大宽度,以使它不会过度挤压或成比例增加。 我们将在侧面添加一些填充,因为我们的块将使用CSS translation属性定位(它们全部位于中间),并且不会影响元素的宽度:

.fs-container {
	margin: 20px auto 50px auto;
	position: relative;
	width: 40%;
	padding: 0 15%;
	max-width: 700px;
	min-width: 220px;
	height: 500px;	
	box-sizing: content-box;
}

Let’s add a realistic shadow under the slider using a pseudo-element. We’ll use a background image for that and setting a background size of 100% will ensure that the shadow resizes with our slider:

让我们使用伪元素在滑块下添加逼真的阴影。 我们将为此使用背景图像,并将背景尺寸设置为100%将确保使用滑块调整阴影的大小:

.fs-container:before {
	content: '';
	position: absolute;
	bottom: -40px;
	background: transparent url(../images/shadow.png) no-repeat center center;
	height: 90px;
	width: 90%;
	left: 5%;
	opacity: 0.8;
	background-size: 100% 100%;
}

The additional wrapper that we’ve added around the slider will have perspective:

我们在滑块周围添加的其他包装将具有透视图:

.fs-wrapper {
	width: 100%;
	height: 100%;
	position: relative;
	perspective: 1000px;
}

The slider itself will need to have the preserve 3d transform-style:

滑块本身将需要保留3d转换样式:

.fs-slider{
	width: 100%;
	height: 100%;
	position: absolute;
	transform-style: preserve-3d;
	pointer-events: none;
}

Each block will be placed in the center by setting the width to 70% and the left value to 15%. We’ll also add a transition to the block since we want to create a neat hover effect:

通过将宽度设置为70%,将左侧值设置为15%,将每个块放置在中间。 由于要创建整洁的悬停效果,我们还将向该块添加过渡:

.fs-block {
	margin: 0;
	position: absolute;
	width: 70%;
	height: 100%;
	left: 15%;
	pointer-events: auto;
	transition: all 1s ease;
}

Now we need to position the blocks. The first one will be moved to the left by setting the translateX value to -100%. By rotating it -35 degrees on the Y-axis, we’ll make it turn away to the back on the left side:

现在我们需要定位块。 通过将translateX值设置为-100%,第一个将向左移动。 通过在Y轴上将其旋转-35度,我们将使其在左侧向后旋转:

.fs-block:nth-child(1) {	
	transform-origin: top right;
	transform: translateX(-100%) rotateY(-35deg);
}

On hover, we will want that panel block to move a bit to the front. We are using Modernizr, so we can define the hover effect only for non-touch devices (the body will have the class “no-touch”):

悬停时,我们希望该面板块稍微向前移动。 我们正在使用Modernizr,因此我们只能为非触摸设备定义悬停效果(主体将具有“非触摸”类):

.no-touch .fs-block:nth-child(1):hover {
	transform: translateX(-100%) rotateY(-30deg);
}

The middle panel will have a z-index of 100 because we want to ensure that it’s always on top:

中间面板的z索引为100,因为我们要确保它始终位于最上方:

.fs-block:nth-child(2) {
	z-index: 100;
}

The last block will be moved right and rotated to the other side:

最后一块将向右移动并旋转到另一侧:

.fs-block:nth-child(3) {
	transform-origin: top left;
	transform: translateX(100%) rotateY(35deg);
}

And on hover we’ll slightly move it to the front:

悬停时,我们将其稍微移到最前面:

.no-touch .fs-block:nth-child(3):hover {
	transform: translateX(100%) rotateY(30deg);
}

Let’s add some semi-transparent overlays to the panels in order to make them look more realistic. We’ll use the pseudo-class :after for that and we0ll make it overflow 1px (to fix a little gap that might show up because of rounding errors of the width):

让我们向面板添加一些半透明的叠加层,以使它们看起来更逼真。 为此,我们将使用伪类:after,并使它溢出1px(以修复由于宽度的舍入误差而可能显示的一些间隙):

.fs-block:after{
	content: '';
	position: absolute;
	width: 100%;
	height: 100%;
	z-index: 1000;
	pointer-events: none;
	box-sizing: content-box;
	border-left: 1px solid rgba(119,119,119,1);
	border-right: 1px solid rgba(119,119,119,1);
	left: -1px;
}

Each block will have a different type of gradient:

每个块将具有不同的渐变类型:

.fs-block:nth-child(1):after {
	background: 
		linear-gradient(
			to right, 
			rgba(0,0,0,0.65) 0%,
			rgba(0,0,0,0.2) 100%
		);
}

The following gradient for the middle panel will add a slightly bended effect:

中间面板的以下渐变将添加稍微弯曲的效果:

.fs-block:nth-child(2):after {
	opacity: 0.8;
	background: 
		linear-gradient(
			to right, 
			rgba(0,0,0,0.5) 0%,
			rgba(0,0,0,0.12) 21%,
			rgba(0,0,0,0.03) 31%,
			rgba(0,0,0,0) 50%,
			rgba(0,0,0,0.03) 70%,
			rgba(0,0,0,0.12) 81%,
			rgba(0,0,0,0.5) 100%
		);
}

The last block will have the reverse gradient of the first one:

最后一块将具有与第一个块相反的梯度:

.fs-block:nth-child(3):after {
	background: 
		linear-gradient(
			to right, 
			rgba(0,0,0,0.2) 0%,
			rgba(0,0,0,0.65) 100%
		);
}

Now, let’s style the figure elements. They will be positioned absolutely and fill all the block element:

现在,让我们设置图元素的样式。 它们将绝对定位并填充所有块元素:

.fs-block figure {
	width: 100%;
	height: 100%;
	margin: 0;
	position: absolute;
	top: 0;
	left: 0;
	overflow: hidden;
	z-index: 1;
}

The idea is to add another figure to a block when we navigate. So we need to set the z-index of the first figure higher so that the added figure does not show up. Then we will animate the width of the first figure to 0%, which will reveal the second one:

我们的想法是在导航时将另一个图形添加到块中。 因此,我们需要将第一个图形的z-index设置得较高,以使添加的图形不会出现。 然后,我们将第一个图形的宽度设置为0%,这将显示第二个图形的宽度:

.fs-block figure:first-child{
	z-index: 10;
}

The image will also be set to position absolute:

该图像还将被设置为绝对位置:

.fs-block figure img {
	position: absolute;
	top: 0;
	left: 0;
	display: block;
}

The figcation element will have a semi-transparent background and we will add a transition. This transition will happen when we add the class fs-transition to it (we’ll do that when we navigate):

figcation元素将具有半透明的背景,我们将添加一个过渡。 当我们向其添加类fs-transition时,将发生这种过渡(导航时将执行此操作):

.fs-block figcaption {
	padding: 0 20px;
	margin: 0;
	position: absolute;
	width: 100%;
	top: 25%;
	background: rgba(0,0,0,0.4);
	overflow: hidden;
	height: 0%;
	opacity: 0;
	text-align: center;
	transition: all 700ms cubic-bezier(0, 0, .15, 1);
}

.fs-block figcaption.fs-transition {
	height: 35%;
	opacity: 1;
}

Let’s style the text elements:

让我们设置文本元素的样式:

.fs-block figcaption h3 {
	font-size: 40px;
	line-height: 40px;
	margin: 0;
	padding: 20px 0;
	color: #fff;
	text-shadow: 1px 1px 1px rgba(0,0,0,0.3);
	font-family: 'Prata', serif;
	font-weight: normal;
}

.fs-block figcaption p {
	color: #fff;
	padding: 20px 0;
	margin: 0;
	text-shadow: 1px 1px 1px rgba(0,0,0,0.2);
	border-top: 1px solid rgba(255,255,255,0.2);
	box-shadow: 0 -1px 0 rgba(0,0,0,0.3);
}

The navigation will be placed in the bottom right corner:

导航将放置在右下角:

.fs-navigation {
	position: absolute;
	z-index: 2000;
	bottom: 10px;
	right: 15%;
	margin-right: 15px;
	user-select: none;
}

The spans will be used as the navigation arrows and they will be floating left and we’ll add the arrow as a background image:

跨度将用作导航箭头,它们将向左浮动,我们将把箭头添加为背景图像:

.fs-navigation span {
	float: left;
	width: 26px;
	height: 26px;
	border-radius: 4px;
	text-indent: -90000px;
	cursor: pointer;
	opacity: 0.6;
	margin-right: 3px;
	background: rgba(0,0,0,0.4) url(../images/arrow.png) no-repeat 50% 50%;
	pointer-events: auto;
}

The second span will be rotated so that the arrow points to the right:

第二个跨度将被旋转,以使箭头指向右侧:

.fs-navigation span:nth-child(2) {
	transform: rotate(180deg);
}

On hover we will increase the opacity:

悬停时,我们将增加不透明度:

.fs-navigation span:hover{
	opacity: 1;
}

Now, let’s add the transitions for the sliding effect. Each panel will have a different delay. Since we always want to animate a kind of swipe from the right, the first panel will have the highest delay. On the other hand, the third one will have no delay. The timing-function will be a custom cubic-bezier:

现在,让我们添加滑动效果的过渡。 每个面板会有不同的延迟。 由于我们一直想从右向动画滑动,因此第一个面板的延迟最大。 另一方面,第三个不会延迟。 计时功能将是自定义三次贝塞尔曲线:

.fs-block:nth-child(1) figure {
	transition: width 900ms cubic-bezier(0, 0, .15, 1) 600ms;
}
.fs-block:nth-child(2) figure {
	transition: width 900ms cubic-bezier(0, 0, .15, 1) 300ms;
}
.fs-block:nth-child(3) figure {
	transition: width 900ms cubic-bezier(0, 0, .15, 1);
}

If you want to try different cubic-bezier timing functions, try this nice online tool.

如果您想尝试不同的三次贝塞尔定时功能,请尝试使用此不错的在线工具

Last, but not least, let’s add some media queries for adjusting the size of the text elements:

最后但并非最不重要的一点,让我们添加一些媒体查询来调整文本元素的大小:

/* Media Queries */

@media screen and (max-width: 1024px) {
	.fs-block figcaption h3 {
		font-size: 26px;
	}
}

@media screen and (max-width: 768px) {
	.fs-block figcaption {
		padding: 0 10px;
	}
	.fs-block figcaption h3 {
		font-size: 16px;
		padding: 10px 0;
	}
	.fs-block figcaption p {
		font-size: 13px;
	}
}

And that’s all the style. Now, let’s look at the JavaScript.

这就是所有样式。 现在,让我们看一下JavaScript。

JavaScript (The JavaScript)

Our plugin options will only have the autoplay settings. Like we have seen before, we set the transitions configuration in the CSS.

我们的插件选项将仅具有自动播放设置。 如我们之前所见,我们在CSS中设置了transitions配置。

$.ImgSlider.defaults	= {
	autoplay	: false,
	interval	: 4000
};

We will start by preloading all the images and once that’s done we will execute the _init function:

我们将从预加载所有图像开始,一旦完成,我们将执行_init函数:


_init				: function( options ) {

	// options
	this.options			= $.extend( true, {}, $.ImgSlider.defaults, options );

	this.current			= 0;

	// https://github.com/twitter/bootstrap/issues/2870
	var transEndEventNames	= {
		'WebkitTransition'	: 'webkitTransitionEnd',
		'MozTransition'		: 'transitionend',
		'OTransition'		: 'oTransitionEnd',
		'msTransition'		: 'MSTransitionEnd',
		'transition'		: 'transitionend'
	};
	this.transEndEventName	= transEndEventNames[ Modernizr.prefixed('transition') ];

	// the initial elements
	this.$initElems			= this.$el.children( 'figure' );
	// total number of elements
	this.initElemsCount		= this.$initElems.length;

	if( this.initElemsCount < 3 ) {

		return false;

	}

	// build layout
	this._layout();
	// init events
	this._initEvents();

	// autoplay on
	if( this.options.autoplay ) {

		this._startSlideshow();

	}

}

Here we are basically caching some elements and initializing some variables to be used later. If we have more than three items or images, we will build the structure mentioned before. We also set the window resize event.

在这里,我们基本上是缓存一些元素并初始化一些变量以供以后使用。 如果我们有三个以上的项目或图像,我们将构建前面提到的结构。 我们还设置了窗口调整大小事件。

Finally, if the autoplay option is set to true, we trigger the auto slideshow.

最后,如果将自动播放选项设置为true,我们将触发自动幻灯片放映。


_layout				: function() {

	this.$initElems.wrapAll( '<div class="fs-temp"></div>' ).hide();

	this.$initElems
		.filter( ':lt(3)' )
		.clone()
		.show()
		.prependTo( this.$el )
		.wrap( '<div class="fs-block"></div>' );

	this.$el
		.wrap( '<section class="fs-container"></section>' )
		.wrap( '<div class="fs-wrapper"></div>' );

	this.$blocks	= this.$el.children( 'div.fs-block' );

	// cache the 3 main blocks
	this.$blockL	= this.$blocks.eq( 0 );
	this.$blockC	= this.$blocks.eq( 1 );
	this.$blockR	= this.$blocks.eq( 2 );

	this.$blockC.find( 'figcaption' ).addClass( 'fs-transition' );

	// all items
	this.$temp		= this.$el.find( 'div.fs-temp' );

	// resize images
	this._resizeBlocks();

	// add navigation if needed
	if( this.initElemsCount > 3 ) {

		var $nav = $( '<nav class="fs-navigation"><span>Previous</span><span>Next</span></nav>' ).appendTo( this.$el.parent() );

		// next and previous
		this.$navPrev	= $nav.find( 'span:first' );
		this.$navNext	= $nav.find( 'span:last' );

		this._initNavigationEvents();

	}

}

The _layout function will make sure that the first three items will be the ones visible in our 3d structure. All the initial items will be hidden and wrapped in the fs-temp division.

_layout函数将确保前三个项目在我们的3d结构中可见。 所有初始项都将被隐藏并包装在fs-temp分区中。

We also need to resize each image according to its wrapper size. The main item’s description (the middle item) is shown while all the others stay hidden. Last, we create the navigation buttons and initialize their events, if we have more than three items.

我们还需要根据其包装大小调整每个图像的大小。 显示主要项目的描述(中间项目),而其他所有项目则保持隐藏。 最后,如果我们有三个以上的项目,则创建导航按钮并初始化其事件。


_initNavigationEvents	: function() {

	var _self = this;

	this.$navPrev.on( 'click.imgslider', function() {

		if( _self.options.autoplay ) {

			clearTimeout( _self.slideshow );
			_self.options.autoplay	= false;

		}

		_self._navigate( 'left' );

	} );
	this.$navNext.on( 'click.imgslider', function() {

		if( _self.options.autoplay ) {

			clearTimeout( _self.slideshow );
			_self.options.autoplay	= false;

		}

		_self._navigate( 'right' );

	} );

}

_navigate				: function( dir ) {

	if( this.isAnimating === true ) {

		return false;

	}

	this.isAnimating = true;

	var _self	= this,
		$items	= this.$temp.children(),
		LIndex, CIndex, RIndex;

	this.$blocks.find( 'figcaption' ).hide().css( 'transition', 'none' ).removeClass( 'fs-transition' );

	if( dir === 'right' ) {

		LIndex = this.current + 1;
		CIndex = this.current + 2;
		RIndex = this.current + 3;

		if( LIndex >= this.initElemsCount ) {

			LIndex -= this.initElemsCount

		}

		if( CIndex >= this.initElemsCount ) {

			CIndex -= this.initElemsCount

		}

	}
	else if( dir === 'left' ) {

		LIndex = this.current - 1;
		CIndex = this.current;
		RIndex = this.current + 1;

		if( LIndex < 0 ) {

			LIndex = this.initElemsCount - 1

		}

	}

	if( RIndex >= this.initElemsCount ) {

		RIndex -= this.initElemsCount

	}

	var $elL	= $items.eq( LIndex ).clone().show(),
		$elC	= $items.eq( CIndex ).clone().show(),
		$elR	= $items.eq( RIndex ).clone().show();

	// resize images
	$elL.children( 'img' ).css( this.$blockL.data( 'imgstyle' ) );
	$elC.children( 'img' ).css( this.$blockC.data( 'imgstyle' ) );
	$elR.children( 'img' ).css( this.$blockR.data( 'imgstyle' ) );

	this.$blockL.append( $elL );
	this.$blockC.append( $elC );
	this.$blockR.append( $elR );

	// now show new images

	var $slides = this.$blocks.find( 'figure:first' ).css( 'width', '0%');

	if( Modernizr.csstransitions ) {

		$slides.on( this.transEndEventName, function( event ) {

			var $this 		= $( this ),
				blockIdx	= $this.parent().index('');

			_self._slideEnd( dir, blockIdx, $elC );

			$this.off( _self.transEndEventName ).remove();

		} );

	}
	else {

		$slides.each( function() {

			var $this 		= $( this ),
				blockIdx	= $this.parent().index('');

			_self._slideEnd( dir, blockIdx, $elC );

		} );

		this._slideEnd();

	}

}

The _navigate function takes control of which items will be positioned in the three visible blocks. We insert each of these item’s figure inside the block, resize the new images, and animate the width property of that same current block’s figure to 0px. In the end, we remove it leaving the new figure in its place. Also, we keep showing the middle block’s description while hiding all the others. This and also updating the current variable is done in the _slideEnd function:

_navigate函数控制将哪些项目放置在三个可见块中。 我们将这些项目的每个图形插入到块中,调整新图像的大小,并将同一当前块图形的width属性设置为0px。 最后,我们将其删除,而将新图形保留在原处。 同样,我们继续显示中间块的描述,同时隐藏所有其他块。 并通过_slideEnd函数完成当前变量的更新:


_slideEnd				: function( dir, blockIdx, $main ) {

	if( blockIdx === 0 ) {

		if( this.current === this.initElemsCount - 1 && dir === 'right' ) {

			this.current = 0;

		}
		else if( this.current === 0 && dir === 'left' ) {

			this.current = this.initElemsCount - 1;

		}
		else {

			( dir === 'right' ) ? ++this.current : --this.current;

		}

		this.isAnimating = false;

	}
	else if( blockIdx === 1 ) {

		$main.find( 'figcaption' ).addClass( 'fs-transition' );

	}

}

The last thing we need to take care is when the user resizes the window. We need to resize the visible block images accordingly. Like we said before, this is also done once _layout is called:

我们需要注意的最后一件事是用户调整窗口大小时。 我们需要相应地调整可见块图像的大小。 就像我们之前说过的,一旦_layout被调用,这也将完成:


_initEvents				: function() {

	var _self = this;

	$window.on( 'debouncedresize.imgslider', function() {

		_self._resizeBlocks();

	} );

},
// resize the images
_resizeBlocks			: function() {

	var _self = this;

	this.$blocks.each( function( i ) {

		var $el 	= $( this ).children( 'figure' ),
			$img	= $el.children( 'img' ),
			dim		= _self._getImageDim( $img.attr( 'src' ), { width : $el.width(), height : $el.height() } );

		// save the image dimentions
		switch( i ) {
			case 0 : _self.$blockL.data( 'imgstyle', dim ); break;
			case 1 : _self.$blockC.data( 'imgstyle', dim ); break;
			case 2 : _self.$blockR.data( 'imgstyle', dim ); break;
		};

		// apply style
		$img.css( dim );

	} );

}

And that’s it! I hope you enjoyed this tutorial and find it useful!

就是这样! 我希望您喜欢本教程并发现它有用!

翻译自: https://tympanus.net/codrops/2012/08/16/triple-panel-image-slider/

jquery 图像滑块

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值