Chào mừng bạn đã đến với diễn đàn Designer Việt Nam, hãy đăng ký thành viên để có thể dễ dàng cùng nhau trau dồi kiến thức đồ họa nhé!

[CSS3 - jQuery] Slideshow ảnh 3D kiểu mới

Chủ đề thuộc danh mục 'HTML - CSS - JS - PHP - ASP' được đăng bởi boyplay, 9/9/12.

  1. boyplay Thành viên cấp 2

    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.
    [IMG]

    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 itmixtape 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 mixtapeskateboard 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 itmixtape 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 {
        
    margin20px auto 50px auto;
        
    positionrelative;
        
    width40%;
        
    padding0 15%;
        
    max-width700px;
        
    min-width220px;
        
    height500px;
        
    box-sizingcontent-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'';
        
    positionabsolute;
        
    bottom: -40px;
        
    backgroundtransparent url(../images/shadow.pngno-repeat center center;
        
    height90px;
        
    width90%;
        
    left5%;
        
    opacity0.8;
        
    background-size100100%;
    }
    Thêm 1 wrapper để tạo ra hiệu ứng xa gần.

    PHP:
    .fs-wrapper {
        
    width100%;
        
    height100%;
        
    positionrelative;
        
    perspective1000px;
    }
    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{
        
    width100%;
        
    height100%;
        
    positionabsolute;
        
    transform-stylepreserve-3d;
        
    pointer-eventsnone;
    }
    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 {
        
    margin0;
        
    positionabsolute;
        
    width70%;
        
    height100%;
        
    left15%;
        
    pointer-eventsauto;
        
    transitionall 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-origintop right;
        
    transformtranslateX(-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 {
        
    transformtranslateX(-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-index100;
    }
    Khối cuối cùng sẽ di chuyển qua bên phải.
    PHP:
    .fs-block:nth-child(3) {
        
    transform-origintop left;
        
    transformtranslateX(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 {
        
    transformtranslateX(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'';
        
    positionabsolute;
        
    width100%;
        
    height100%;
        
    z-index1000;
        
    pointer-eventsnone;
        
    box-sizingcontent-box;
        
    border-left1px solid rgba(119,119,119,1);
        
    border-right1px 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.650%,
                
    rgba(0,0,0,0.2100%
            );
    }
    Gadient này cho panel ở giữa
    PHP:
    .fs-block:nth-child(2):after {
        
    opacity0.8;
        
    background:
            
    linear-gradient(
                
    to right,
                
    rgba(0,0,0,0.50%,
                
    rgba(0,0,0,0.1221%,
                
    rgba(0,0,0,0.0331%,
                
    rgba(0,0,0,050%,
                
    rgba(0,0,0,0.0370%,
                
    rgba(0,0,0,0.1281%,
                
    rgba(0,0,0,0.5100%
            );
    }
    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.20%,
                
    rgba(0,0,0,0.65100%
            );
    }
    Với các đối tượng hình ảnh, chúng sẽ đc định vị trí là absolutely

    PHP:
    .fs-block figure {
        
    width100%;
        
    height100%;
        
    margin0;
        
    positionabsolute;
        
    top0;
        
    left0;
        
    overflowhidden;
        
    z-index1;
    }

    ý 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-index10;
    }
    Các hình ảnh sẽ đc cho vị trí là absolute

    PHP:
    .fs-block figure img {
        
    positionabsolute;
        
    top0;
        
    left0;
        
    displayblock;
    }
    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 {
        
    padding0 20px;
        
    margin0;
        
    positionabsolute;
        
    width100%;
        
    top25%;
        
    backgroundrgba(0,0,0,0.4);
        
    overflowhidden;
        
    height0%;
        
    opacity0;
        
    text-aligncenter;
        
    transitionall 700ms cubic-bezier(00.151);
    }
     
    .
    fs-block figcaption.fs-transition {
        
    height35%;
        
    opacity1;
    }
    Dành cho phần text phía trước
    PHP:
    .fs-block figcaption h3 {
        
    font-size40px;
        
    line-height40px;
        
    margin0;
        
    padding20px 0;
        
    color#fff;
        
    text-shadow1px 1px 1px rgba(0,0,0,0.3);
        
    font-family'Prata'serif;
        
    font-weightnormal;
    }
     
    .
    fs-block figcaption p {
        
    color#fff;
        
    padding20px 0;
        
    margin0;
        
    text-shadow1px 1px 1px rgba(0,0,0,0.2);
        
    border-top1px solid rgba(255,255,255,0.2);
        
    box-shadow-1px 0 rgba(0,0,0,0.3);
    }
    Nút điều hướng
    PHP:
    .fs-navigation {
        
    positionabsolute;
        
    z-index2000;
        
    bottom10px;
        
    right15%;
        
    margin-right15px;
        
    user-selectnone;
    }
    Thẻ Span đc sử dụng để chứa 2 mũi tên điều hướng
    PHP:
    .fs-navigation span {
        
    floatleft;
        
    width26px;
        
    height26px;
        
    border-radius4px;
        
    text-indent: -90000px;
        
    cursorpointer;
        
    opacity0.6;
        
    margin-right3px;
        
    backgroundrgba(0,0,0,0.4url(../images/arrow.pngno-repeat 5050%;
        
    pointer-eventsauto;
    }
    the span còn lại sẽ xoay qua phải
    PHP:
    .fs-navigation span:nth-child(2) {
        
    transformrotate(180deg);
    }
    Khi rê chuột lại nó sẽ tăng opacity lên
    PHP:
    .fs-navigation span:hover{
        
    opacity1;
    }
    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(1figure {
        
    transitionwidth 900ms cubic-bezier(00.151600ms;
    }
    .
    fs-block:nth-child(2figure {
        
    transitionwidth 900ms cubic-bezier(00.151300ms;
    }
    .
    fs-block:nth-child(3figure {
        
    transitionwidth 900ms cubic-bezier(00.151);
    }
    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-width1024px) {
        .
    fs-block figcaption h3 {
            
    font-size26px;
        }
    }
     
    @
    media screen and (max-width768px) {
        .
    fs-block figcaption {
            
    padding0 10px;
        }
        .
    fs-block figcaption h3 {
            
    font-size16px;
            
    padding10px 0;
        }
        .
    fs-block figcaption p {
            
    font-size13px;
        }
    }
    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            = $.extendtrue, {}, $.ImgSlider.defaultsoptions );
     
        
    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  transEndEventNamesModernizr.prefixed('transition') ];
     
        
    // the initial elements
        
    this.$initElems        this.$el.children'figure' );
        
    // total number of elements
        
    this.initElemsCount    this.$initElems.length;
     
        if( 
    this.initElemsCount ) {
     
            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()
            .
    prependTothis.$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);
        
    this.$blockC    this.$blocks.eq);
        
    this.$blockR    this.$blocks.eq);
     
        
    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 ) {
     
            var 
    $nav = $( '<nav class="fs-navigation"><span>Previous</span><span>Next</span></nav>' ).appendTothis.$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(),
            
    LIndexCIndexRIndex;
     
        
    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 ) {
     
                
    LIndex this.initElemsCount 1
     
            
    }
     
        }
     
        if( 
    RIndex >= this.initElemsCount ) {
     
            
    RIndex -= this.initElemsCount
     
        
    }
     
        var 
    $elL    $items.eqLIndex ).clone().show(),
            
    $elC    $items.eqCIndex ).clone().show(),
            
    $elR    $items.eqRIndex ).clone().show();
     
        
    // resize images
        
    $elL.children'img' ).cssthis.$blockL.data'imgstyle' ) );
        
    $elC.children'img' ).cssthis.$blockC.data'imgstyle' ) );
        
    $elR.children'img' ).cssthis.$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.onthis.transEndEventName, function( event ) {
     
                var 
    $this      = $( this ),
                    
    blockIdx    $this.parent().index('');
     
                
    _self._slideEnddirblockIdx$elC );
     
                
    $this.off_self.transEndEventName ).remove();
     
            } );
     
        }
        else {
     
            
    $slides.each( function() {
     
                var 
    $this      = $( this ),
                    
    blockIdx    $this.parent().index('');
     
                
    _self._slideEnddirblockIdx$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( dirblockIdx$main ) {
     
        if( 
    blockIdx === ) {
     
            if( 
    this.current === this.initElemsCount && dir === 'right' ) {
     
                
    this.current 0;
     
            }
            else if( 
    this.current === && dir === 'left' ) {
     
                
    this.current this.initElemsCount 1;
     
            }
            else {
     
                ( 
    dir === 'right' ) ? ++this.current : --this.current;
     
            }
     
            
    this.isAnimating false;
     
        }
        else if( 
    blockIdx === ) {
     
            
    $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( ) {
     
            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( ) {
                case 
    _self.$blockL.data'imgstyle'dim ); break;
                case 
    _self.$blockC.data'imgstyle'dim ); break;
                case 
    _self.$blockR.data'imgstyle'dim ); break;
            };
     
            
    // apply style
            
    $img.cssdim );
     
        } );
     
    }
    Đó 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
    nguoihanhtinhlabanbaonylong thích bài viết này.
Từ khóa: CSS, jquery, Slideshow, 3D

Ủng hộ bài viết này