Trong bài viết này, chúng ta sẽ làm 1 slide ảnh với 3 panel, 2 panel 2 bên sẽ nghiêng 1 chút để tạo hiệu ứng 3D. Các hình ảnh đc sử dụng là của geishaboy500 và chúng đã đc cáp phép sử dụng bởi Creative Commons Attribution 2.0 Generic (CC BY 2.0). Xem demo https://dl.dropbox.com/u/8612983/Thu thuat WEB/TriplePanelImageSlider/index.html Đầu tiên là phần HTML PHP: <div class="fs-slider" id="fs-slider"> <figure> <img src="http://windowsz.net/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="http://windowsz.net/images/2.jpg" alt="image02" /> <figcaption> <h3>Quintessential</h3> <p>Cardigan craft beer mixtape, skateboard forage fixie truffaut messenger bag. </p> </figcaption> </figure> <!-- ... --> </div> Chúng ta sẽ làm jQuery thay đổi cấu trúc như sau PHP: <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="http://windowsz.net/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 --> Mỗi hình sẽ đc bao quanh một class fs-block. Và chúng ta thêm cho chúng các thành phần điều hướng cho chúng. Bây giờ qua phần CSS Để hình ảnh trượt đc đẹp, chúng ta cần xác định phần trăm độ rộng của mỗi tấm hình. Tuy nhiên chúng ta khó có thể xác định đc độ rộng lớn nhất và nhỏ nhất cần thiết để nó không bị chệch ra ngoài, nên chúng ta sẽ thêm vào 1 ít padding vào bên cạnh chúng bởi vì các khối sẽ sử dụng thuộc tính CSS translte để định vị trí cho chúng (chúng sẽ nằm ở giữa) và điều đó sẽ không ảnh hưởng đến chiều rộng của phần tử. PHP: .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;} Chúng ta sẽ thêm bóng đổ cho chúng bằng cách sử dụng pseudo-element. Chúng ta sẽ sử dụng 1 tấm ảnh và cho nó là 100%. Như vậy nó sẽ thay đổi theo hình ảnh của chúng ta. PHP: .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%;} Thêm 1 wrapper để tạo ra hiệu ứng xa gần. PHP: .fs-wrapper { width: 100%; height: 100%; position: relative; perspective: 1000px;} Bản thân của slider cũng cần phải duy trì phong cách 3D của nó PHP: .fs-slider{ width: 100%; height: 100%; position: absolute; transform-style: preserve-3d; pointer-events: none;} Các khối sẽ đc đặt vào giữa bằng cách cho độ rộng là 70% và bên trái là 30%. Chúng ta cũng sẽ thêm 1 chút hiệu ứng chuyển động khi rê chuột lại nó. PHP: .fs-block { margin: 0; position: absolute; width: 70%; height: 100%; left: 15%; pointer-events: auto; transition: all 1s ease;} bây gờ chúng ta cần cố định các khối lại. Đầu tiên sẽ di chuyển qua bên trái bằng cách chỉnh giá trị của translateX là -100%. Xoay nó 1 góc -35 độ theo trục Y, chúng ta sẽ xoay nó ra sau phía bên trái PHP: .fs-block:nth-child(1) { transform-origin: top right; transform: translateX(-100%) rotateY(-35deg);} Khi rê chuột lại, chúng ta cần các khối panel di chuyển 1 chút về phía trước, Chúng ta cần sử dụng Modernizr, vì vậy chúng ta có thể xác định hiệu ứng hover chỉ với các thiết bị không phải cảm ứng. PHP: .no-touch .fs-block:nth-child(1):hover { transform: translateX(-100%) rotateY(-30deg);} Panel chính giữa sẽ có giá trị z-index là 100 bởi vì chúng ta muốn nó luôn nằm trên cùng PHP: .fs-block:nth-child(2) { z-index: 100;} Khối cuối cùng sẽ di chuyển qua bên phải. PHP: .fs-block:nth-child(3) { transform-origin: top left; transform: translateX(100%) rotateY(35deg);} Và khi rê chuột lại nó sẽ nhích lên trước 1 chút PHP: .no-touch .fs-block:nth-child(3):hover { transform: translateX(100%) rotateY(30deg);} Chúng ta sẽ thêm 1 phần tử trong suốt mờ phía trước, chúng ta sẽ dùng pseudo-class :after và cho nó overflow = 1px (để sửa chữa một khoảng cách nhỏ có thể hiển thị vì lỗi làm tròn chiều rộng) PHP: .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;} Mỗi khối sẽ có kỉu Gadient khác nhau PHP: .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% );} Gadient này cho panel ở giữa PHP: .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% );} Khối cuối cùng sẽ có Gadient ngược lại PHP: .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% );} Với các đối tượng hình ảnh, chúng sẽ đc định vị trí là absolutely PHP: .fs-block figure { width: 100%; height: 100%; margin: 0; position: absolute; top: 0; left: 0; overflow: hidden; z-index: 1;} ý tưởng ở đây là thêm 1 hình ảnh khác để lấp đầy khi chúng di chuyển. Vì vậy chúng ta sẽ thiết lập z-index của hình ảnh thứ nhất cao hơn, sau đó chúng ta sẽ thay đổi độ rộng của hình đầu tiên về 0%, và nó sẽ hiện lên hình thứ 2 PHP: .fs-block figure:first-child{ z-index: 10;} Các hình ảnh sẽ đc cho vị trí là absolute PHP: .fs-block figure img { position: absolute; top: 0; left: 0; display: block;} Các hình ảnh có lớp trong suốt phía trước và chúng ta sẽ thêm cho chúng 1 hiệu ứng chuyển động kèm theo. Chuyển động sẽ xảy ra khi ta thêm class fs-transition. PHP: .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;} Dành cho phần text phía trước PHP: .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);} Nút điều hướng PHP: .fs-navigation { position: absolute; z-index: 2000; bottom: 10px; right: 15%; margin-right: 15px; user-select: none;} Thẻ Span đc sử dụng để chứa 2 mũi tên điều hướng PHP: .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 span còn lại sẽ xoay qua phải PHP: .fs-navigation span:nth-child(2) { transform: rotate(180deg);} Khi rê chuột lại nó sẽ tăng opacity lên PHP: .fs-navigation span:hover{ opacity: 1;} bây giờ chúng ta sẽ cho hiệu ứng chuyển động khi nhấp vào các mũi tên, các khối sẽ có thời gian delay khác nhau. Vì chúng ta muốn có hiệu ứng kiểu xoáy phía bên phải, do vậy,panel đầu tên sẽ có delay cao nhất và cái thứ 3 sẽ ko có delay. Thời gian dó sẽ đc tùy chỉnh dựa vào vào thuộc tính cubic-bezier. PHP: .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);} nếu bạn thik kỉu khác có thể thâm khảo tại đây: cubic-bezier.com Cuối cùng, thêm 1 chút cho phần text PHP: /* 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; }} Qua JavaScript Thuộc tính của plug in đc tự động thiết lập, như chúng ta thấy ở trên, ta đã thiết lập qua CSS PHP: $.ImgSlider.defaults = { autoplay : false, interval : 4000}; Chúng ta sẽ tiến hành load tất cả ảnh lên trước, khi load xong chúng ta sẽ thực hiện các lệnh _init: PHP: _init : function( options ) { // options this.options = $.extend( true, {}, $.ImgSlider.defaults, options ); this.current = 0; // [URL]https://github.com/twitter/bootstrap/issues/2870[/URL] 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(); } } Ở đây chúng ta có thêm vài thiết lập cho bộ nhớ đệm để sử dụng về sau. Nếu có nhìu hơn 3 hình, chúng ta sẽ cần thiết lập lại các phần đã đề cập ở trên. Cuối cùng nếu thiết lập autoplay là true, các hình ảnh sẽ chạy 1 cách tự động. PHP: _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(); } } Chức năng _layout sẽ đảm bảo rằng ba hình đầu tiên sẽ là những hình có thể nhìn thấy trong cấu trúc 3D của chúng tôi. Tất cả các hạng mục ban đầu sẽ được ẩn và được bao bọc trong fs-temp. Chúng ta cũng cần thay đổi kích thước mỗi ảnh theo kích thước wrapper của nó. Các phần Mô tả (hạng mục giữa) được hiển thị trong khi tất cả những cai1 khác được ẩn. Cuối cùng, chúng tôi tạo ra các nút điều hướng và khởi tạo các sự kiện cho chúng, nếu chúng ta có nhiều hơn ba mục. PHP: _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(); } } Chúc năng _navigate sẽ nằm quyền điều khiển các item đc đặt vào trong 3 khối. Chúng ta thêm hình ảnh vào mỗi item bên trong khối, thay đổi kích thước ảnh đó và cho thuộc tính của độ rộng về 0px, cuối cùng, chúng ta loại bỏ nó và thay thế bằng hình mới, tuy nhiên chúng ta giữ phần mô tả ở giữa lại trong khi ẩn tất cả các thứ khác. Nó sẽ đc cập nhật lại khi hoàn tất bới _slideEnd. PHP: _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' ); } } Và cuối cùng là, khi người dùng thay đổi kích thước màn hình, thì nó cũng sẽ cần phải thay đổi, lúc này hàm _layout sẽ đc gọi lên. PHP: _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 ); } ); } Đó là tất cả. Chúc bạn thành công Dowload file demo: http://windowsz.net/attachments/f23...ow-anh-3d-kieu-moi-triplepanelimageslider.zip Đây là bài của tác giả Mary You, tớ chỉ dịch lại thôi nha, nên khả năng hỗ trợ rất ít. Hj hj Boyplay