SlideShow / Slider Konten Transisi Miring


Laman landas FWA memiliki slider konten yang sangat bagus yang diputar dengan perspektif 3D pada tangkapan layar dan menjiwai mereka dengan cara yang menarik. Hari ini kami ingin menciptakan bagian dari efek itu dan membuat tayangan slide konten sederhana dengan beberapa animasi 3D keren. Tayangan slide tidak akan sama dengan yang ada di laman FWA: item tidak akan "mengambang" atau bergerak di hover dan kami hanya akan memiliki navigasi sederhana.
Jika Anda telah melihat pengaruhnya di halaman arahan FWA, Anda akan melihat bahwa arah gerakan tangkapan layar acak (bergerak ke atas atau bawah dan meluncur ke samping). Kami ingin mencapai efek yang sama dengan menambahkan beberapa atribut data secara acak yang mengendalikan jenis animasi.
Harap perhatikan bahwa kami akan menggunakan CSS 3D Transforms and CSS Animations yang mungkin tidak berfungsi di browser lama atau seluler.
Untuk demo kami menggunakan beberapa screenshot situs dari Zurb's Responsive Gallery.
Jadi, mari kita mulai!

Markup
Tayangan slide memiliki wadah utama dengan kelas dan ID "slideshow" dan kami dapat menggunakan daftar pesanan untuk slide kami. Setiap item daftar berisi deskripsi dengan judul dan paragraf. Ini juga akan berisi pembagian dengan kelas "tiltview" di mana kita akan menambahkan tangkapan layar kita. Kelas "col" sebuah "baris" akan membantu kita mengatur tata letak yang tepat untuk jangkar bagian dalam:
<div class="slideshow" id="slideshow">
 <ol class="slides">
  <li class="current">
   <div class="description">
    <h2>Some Title</h2>
    <p>Some description</p>
   </div>
   <div class="tiltview col">
    <a href="http://grovemade.com/"><img src="img/1_screen.jpg"/></a>
    <a href="https://tsovet.com/"><img src="img/2_screen.jpg"/></a>
   </div>
  </li>
  <li>
   <div class="description">
    <!-- ... -->
   </div>
   <div class="tiltview row">
    <!-- ... -->
   </div>
  </li>
  <li>
   <!-- ... -->
  </li>
 </ol>
</div>
Kami juga akan menambahkan elemen navigasi di JavaScript kami yang akan kami tempatkan tepat setelah daftar pesanan. Ini akan terdiri dari sebuah nav dengan jumlah bentang yang tepat.
Mari kita sudah memikirkan bagaimana kita akan mengendalikan animasi untuk setiap tangkapan layar. Dalam naskah kami, kami menetapkan atribut data untuk animasi masuk dan keluar secara acak. Kami akan menggunakan data-attributes data-effect-in dan data-effect-out untuk mengendalikan animasi kita di CSS. Kami akan memeriksa nilai untuk atribut tersebut dalam beberapa saat. Mari kita periksa dulu gaya utama slideshow.

CSS
Perhatikan bahwa CSS tidak akan berisi prefiks vendor apapun, namun Anda akan menemukannya di file (-webkit-).
Pembungkus slide dan daftar pesanan kami akan memiliki gaya berikut:
.slideshow {
 position: relative;
 margin-bottom: 100px;
}

.slides {
 list-style: none;
 padding: 0;
 margin: 0;
 position: relative;
 height: 500px;
 width: 100%;
 overflow: hidden;
 background: #ddd;
 color: #333;
}
Tayangan slide akan setinggi 500px dan kita perlu mengatur overflow agar tersembunyi, sehingga kita tidak melihat barangnya terbang keluar.
Saat kami tidak dapat membuat tayangan slide kami karena JavaScript tidak diaktifkan, kami perlu memastikan bahwa semua slide ditampilkan, jadi kami menetapkan ketinggian ke auto:
.no-js .slides {
 height: auto;
}
Setiap item daftar akan diposisikan secara mutlak dan menempati semua lebar dan tinggi yang tersedia. Secara default, kita akan mengatur visibilitas untuk disembunyikan.
Setiap slide juga akan berfungsi sebagai wadah perspektif dan kami akan menentukan nilai perspektif 1600px:
.slides > li {
 width: 100%;
 height: 100%;
 position: absolute;
 visibility: hidden;
 perspective: 1600px;
}
Jangan lupa fallback:
.no-js .slides > li {
 position: relative;
 visibility: visible;
}
Navigasi yang ditambahkan secara dinamis, akan muncul sebagai satu set garis. Setiap item navigasi adalah rentang dan meskipun kami menggunakan garis kecil, kami ingin memastikan bahwa area yang dapat diklik sebenarnya lebih besar. Ini bisa kita simulasikan dengan menambahkan border putih:
.slideshow > nav {
 text-align: center;
 margin-top: 20px;
}

.slideshow > nav span {
 display: inline-block;
 width: 60px;
 height: 25px;
 border-top: 10px solid #fff;
 border-bottom: 10px solid #fff;
 background-color: #ddd;
 cursor: pointer;
 margin: 0 3px;
 transition: background-color 0.2s;
}

.slideshow > nav span:hover {
 background-color: #333;
}

.slideshow > nav span.current {
 background-color: #aaa;
}
Deskripsi akan mengisi setengah dari lebar dan karena kita menginginkan sebuah transisi pada opacity, kita perlu mengaturnya ke 0 awalnya:
.description {
 width: 50%;
 padding: 2em 4em;
 font-size: 1.5em;
 position: relative;
 z-index: 1000;
 opacity: 0;
}

.no-js .description {
 opacity: 1;
}

.description h2 {
 font-size: 200%;
}
Sekarang, mari gaya elemen yang paling penting dalam tayangan slide kami. Pembagian dengan "tiltview" kelas akan membantu kami memasukkan barang-barang kami ke dalam perspektif. Kita perlu menambahkan preserve-3d sebagai gaya transform karena beberapa item dalam perlu berpindah ke sumbu Z dalam beberapa animasi.
Pembungkus "tiltview" akan dipusatkan dengan menetapkan bagian atas hingga 50% dan mengubahnya -50% pada sumbu Y. Kami juga akan memutar di sumbu X dan Z untuk membuat tampilan 3D:
.tiltview {
 position: absolute;
 left: 50%;
 width: 50%;
 top: 50%;
 transform-style: preserve-3d;
 transform: translateY(-50%) rotateX(60deg) rotateZ(35deg);
}
Dan jangkar dan gambar akan memiliki gaya berikut (garis besar membantu menghindari tepian bergerigi di Firefox):
.tiltview a {
 outline: 1px solid transparent;
}

.tiltview a,
.tiltview a img {
 max-width: 100%;
 display: block;
 margin: 0 auto;
}

.tiltview a:first-child {
 margin-bottom: 30px;
}
Untuk kasus baris dan kolom kami akan mengatur lebar sesuai:
.tiltview.row a {
 width: 48%;
 width: calc(50% - 15px);
 margin: 0;
}

.tiltview.row a:nth-child(2) {
 left: 50%;
 left: calc(50% + 15px);
 position: absolute;
 top: 0;
}
Dalam naskah kita kita akan menggunakan kelas "show" dan "hide" untuk mengontrol visibilitas slide:
/* Show/Hide */
.slides > li.current,
.slides > li.show {
 visibility: visible;
}
Deskripsi akan memudar masuk dan keluar:
.description {
 transition: opacity 0.75s;
}

.current .description,
.show .description {
 opacity: 1;
}

.hide .description {
 opacity: 0;
}
Seperti yang telah disebutkan sebelumnya, kita akan mengendalikan animasi dengan menggunakan beberapa atribut data. Kita harus mendefinisikan dua jenis animasi: yang masuk (saat kita menampilkan slide berikutnya) dan yang keluar (saat kita menyembunyikan slide sebelumnya).
Kami ingin bisa menghidupkan item di semua arah yang mungkin, jadi kami memerlukan enam jenis: bergerak ke atas, bergerak ke bawah, geser ke atas, geser ke bawah, geser ke kiri, geser ke kanan. Hal ini membuat total 12 animasi (masuk dan keluar).
Jadi, mari kita definisikan yang pertama untuk memindahkan elemen keluar:
/***********************/
/* Move up */
/***********************/

.hide[data-effect-out="moveUpOut"] .tiltview a {
 animation: moveUpOut 1.5s both;
}

.hide[data-effect-out="moveUpOut"] .tiltview a:nth-child(2) {
 animation-delay: 0.25s;
}

@keyframes moveUpOut {
 25% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateZ(-30px);
 }
 100% {
  transform: translateZ(3000px);
 }
}
Kami mendefinisikan sedikit penundaan animasi untuk item kedua dan kami menggunakan fungsi waktu cubic-bezier kustom untuk menambahkan beberapa momentum yang menarik.
Animasi kedua untuk gerakan ini adalah yang masuk yang memiliki langkah awal dan akhir terbalik:
.show[data-effect-in="moveUpIn"] .tiltview a {
 animation: moveUpIn 1.5s 0.5s both;
}

.show[data-effect-in="moveUpIn"] .tiltview a:nth-child(2) {
 animation-delay: 0.75s;
}

@keyframes moveUpIn {
 0% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateZ(-3000px);
 }
 75% {
  transform: translateZ(30px);
 }
 100% {
  transform: translateZ(0);
 }
}
Seperti yang mungkin Anda perhatikan, kami dapat menyederhanakan penundaan animasi untuk kasus "sembunyikan" dan "pertunjukan", namun menjaga agar kedua aturan dipisahkan memungkinkan adaptasi lebih mudah jika Anda ingin menentukan beberapa penundaan yang berbeda.
Animasi istirahat adalah sebagai berikut:
/***********************/
/* Move down */
/***********************/
.hide[data-effect-out="moveDownOut"] .tiltview a {
 animation: moveDownOut 1.5s both;
}

.hide[data-effect-out="moveDownOut"] .tiltview a:nth-child(2) {
 animation-delay: 0.25s;
}

@keyframes moveDownOut {
 25% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateZ(30px);
 }
 100% {
  transform: translateZ(-3000px);
 }
}

.show[data-effect-in="moveDownIn"] .tiltview a {
 animation: moveDownIn 1.5s 0.5s both;
}

.show[data-effect-in="moveDownIn"] .tiltview a:nth-child(2) {
 animation-delay: 0.75s;
}

@keyframes moveDownIn {
 0% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateZ(3000px);
 }
 75% {
  transform: translateZ(-30px);
 }
 100% {
  transform: translateZ(0);
 }
}

/***********************/
/* Slide up */
/***********************/
.hide[data-effect-out="slideUpOut"] .tiltview a {
 animation: slideUpOut 1.5s both;
}

.hide[data-effect-out="slideUpOut"] .tiltview a:nth-child(2) {
 animation-delay: 0.25s;
}

@keyframes slideUpOut {
 25% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateY(30px);
 }
 100% {
  transform: translateY(-3000px);
 }
}

.show[data-effect-in="slideUpIn"] .tiltview a {
 animation: slideUpIn 1.5s 0.5s both;
}

.show[data-effect-in="slideUpIn"] .tiltview a:nth-child(2) {
 animation-delay: 0.75s;
}

@keyframes slideUpIn {
 0% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateY(3000px);
 }
 75% {
  transform: translateY(-30px);
 }
 100% {
  transform: translateY(0);
 }
}

/***********************/
/* Slide down */
/***********************/
.hide[data-effect-out="slideDownOut"] .tiltview a {
 animation: slideDownOut 1.5s both;
}

.hide[data-effect-out="slideDownOut"] .tiltview.row a:nth-child(2),
.hide[data-effect-out="slideDownOut"] .tiltview.col a:first-child {
 animation-delay: 0.25s;
}

@keyframes slideDownOut {
 25% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateY(-30px);
 }
 100% {
  transform: translateY(3000px);
 }
}

.show[data-effect-in="slideDownIn"] .tiltview a {
 animation: slideDownIn 1.5s 0.5s both;
}

.show[data-effect-in="slideDownIn"] .tiltview.row a:nth-child(2),
.show[data-effect-in="slideDownIn"] .tiltview.col a:first-child {
 animation-delay: 0.75s;
}

@keyframes slideDownIn {
 0% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateY(-3000px);
 }
 75% {
  transform: translateY(30px);
 }
 100% {
  transform: translateY(0);
 }
}

/***********************/
/* Slide left */
/***********************/
.hide[data-effect-out="slideLeftOut"] .tiltview a {
 animation: slideLeftOut 1.5s both;
}

.hide[data-effect-out="slideLeftOut"] .tiltview a:nth-child(2) {
 animation-delay: 0.25s;
}

@keyframes slideLeftOut {
 25% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateX(30px);
 }
 100% {
  transform: translateX(-5000px);
 }
}

.show[data-effect-in="slideLeftIn"] .tiltview a {
 animation: slideLeftIn 1.5s 0.5s both;
}

.show[data-effect-in="slideLeftIn"] .tiltview a:nth-child(2) {
 animation-delay: 0.75s;
}

@keyframes slideLeftIn {
 0% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateX(3000px);
 }
 75% {
  transform: translateX(-30px);
 }
 100% {
  transform: translateX(0);
 }
}

/***********************/
/* Slide right */
/***********************/
.hide[data-effect-out="slideRightOut"] .tiltview a {
 animation: slideRightOut 1.5s both;
}

.hide[data-effect-out="slideRightOut"] .tiltview.col a:nth-child(2),
.hide[data-effect-out="slideRightOut"] .tiltview.row a:first-child {
 animation-delay: 0.25s;
}

@keyframes slideRightOut {
 25% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateX(-30px);
 }
 100% {
  transform: translateX(3000px);
 }
}

.show[data-effect-in="slideRightIn"] .tiltview a {
 animation: slideRightIn 1.5s 0.5s both;
}

.show[data-effect-in="slideRightIn"] .tiltview.col a:nth-child(2),
.show[data-effect-in="slideRightIn"] .tiltview.row a:first-child {
 animation-delay: 0.75s;
}

@keyframes slideRightIn {
 0% {
  animation-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
  transform: translateX(-5000px);
 }
 75% {
  transform: translateX(30px);
 }
 100% {
  transform: translateX(0);
 }
}

Perhatikan bahwa untuk beberapa animasi kita perlu mendefinisikan penundaan animasi untuk anak pertama dan bukan yang kedua. Kita perlu melakukan ini agar jangkar tidak saling tumpang tindih untuk beberapa arah.
Bila kita tidak memiliki dukungan untuk CSS 3D Transforms atau transform-style: preserve-3d, maka kita ingin memberikan fallback sederhana:
/* Fallback for no 3D Transforms and no preserve-3d */
.no-csstransformspreserve3d .show .tiltview a,
.no-csstransformspreserve3d .hide .tiltview a,
.no-csstransforms3d .show .tiltview a,
.no-csstransforms3d .hide .tiltview a {
 animation: none !important;
}

.no-csstransforms3d .tiltview.col {
 top: -50%;
}

.no-csstransforms3d .tiltview.row {
 top: 20px;
}
Dan yang terakhir, namun tidak kalah pentingnya, kita perlu memastikan bahwa kita memiliki tampilan yang masuk akal untuk layar yang lebih kecil. Dalam kasus ini, kami ingin jangkar dengan tangkapan layar mereka menjadi hiasan saja, jadi kami akan menurunkan opacity mereka dan membuatnya tidak dapat diklik:
@media screen and (max-width: 65.3125em) {
 .description,
 .tiltview {
  width: 100%;
 }

 .tiltview {
  left: 0;
  opacity: 0.3;
  pointer-events: none;
 }
}

@media screen and (max-width: 33.75em) {
 .description {
  font-size: 1.1em;
 }

 .slideshow > nav span {
  width: 20px;
  height: 40px;
  margin: 0 10px;
 }
}

@media screen and (max-width: 24em) {
 .slides {
  height: 320px;
 }

 .description {
  font-size: 1em;
  padding: 1.4em;
 }

 .no-csstransforms3d .tiltview.col,
 .no-csstransforms3d .tiltview.row {
  top: 0;
 }
}
Dan itulah gayanya! Ayo kita skrip slideshow kita.

JavaScript
Kita akan memulai dengan menginisialisasi beberapa variabel, seperti dua array dengan nama kelas animasi yang mengontrol masuk dan keluar item kita. Ini akan dipilih secara acak dan disetel ke item saat kami menavigasi slideshow. Variabel lain adalah item, nilai saat dari item yang dipilih (kami menganggap ini akan menjadi yang pertama) dan jumlah item di dalam slider:
function TiltSlider( el, options ) {
 this.el = el;
 // available effects for the animations (animation class names) - when an item comes in or goes out
 this.animEffectsOut = ['moveUpOut','moveDownOut','slideUpOut','slideDownOut','slideLeftOut','slideRightOut'];
 this.animEffectsIn = ['moveUpIn','moveDownIn','slideUpIn','slideDownIn','slideLeftIn','slideRightIn'];
 // the items
 this.items = this.el.querySelector( 'ol.slides' ).children;
 // total number of items
 this.itemsCount = this.items.length;
 if( !this.itemsCount ) return;
 // index of the current item
 this.current = 0;
 this.options = extend( {}, this.options );
 extend( this.options, options );
 this._init();
}
Untuk menavigasi slideshow kita akan menambahkan beberapa tampilan navigasi yang, saat diklik, akan membuat masing-masing item slideshow muncul. Jumlah total bentang akan sama dengan jumlah item. Mari tambahkan navigasi ke komponen kami:
TiltSlider.prototype._addNavigation = function() {
 // add nav "dots"
 this.nav = document.createElement( 'nav' )
 var inner = '';
 for( var i = 0; i < this.itemsCount; ++i ) {
  inner += i === 0 ? '' : '';
 }
 this.nav.innerHTML = inner;
 this.el.appendChild( this.nav );
 this.navDots = [].slice.call( this.nav.children );
}
Selanjutnya, kita perlu mengikat event onclick ke rentang navigasi. Jika kita mengklik yang lain tapi rentang saat ini, maka item saat ini harus dinyalakan dan yang baru harus dinyalakan.
TiltSlider.prototype._initEvents = function() {
 var self = this;
 // show a new item when clicking the navigation "dots"
 this.navDots.forEach( function( dot, idx ) {
  dot.addEventListener( 'click', function() {
   if( idx !== self.current ) {
    self._showItem( idx );
   }
  } );
 } );
}
Kita perlu referensi dan bekerja dengan item saat ini dan juga yang berikutnya yang harus muncul. Kami akan menambahkan dan menghapus kelas dari keduanya untuk menerapkan animasi masing-masing. Animasi (yaitu nilai atribut data) sendiri akan diambil secara acak dari animEffectsOut dan animEffectsIn array seperti yang dijelaskan sebelumnya.
TiltSlider.prototype._showItem = function( pos ) {
 if( this.isAnimating ) {
  return false;
 }
 this.isAnimating = true;

 classie.removeClass( this.navDots[ this.current ], 'current' );

 var self = this,
  // the current item
  currentItem = this.items[ this.current ];

 this.current = pos;

 // next item to come in
 var nextItem = this.items[ this.current ],
  // set random effects for the items
  outEffect = this.animEffectsOut[ Math.floor( Math.random() * this.animEffectsOut.length ) ],
  inEffect = this.animEffectsIn[ Math.floor( Math.random() * this.animEffectsOut.length ) ];

 currentItem.setAttribute( 'data-effect-out', outEffect );
 nextItem.setAttribute( 'data-effect-in', inEffect );

 classie.addClass( this.navDots[ this.current ], 'current' );

 var cntAnims = 0,
  // the number of elements that actually animate inside the current item
  animElemsCurrentCount = currentItem.querySelector( '.tiltview' ).children.length, 
  // the number of elements that actually animate inside the next item
  animElemsNextCount = nextItem.querySelector( '.tiltview' ).children.length,
  // keep track of the number of animations that are terminated
  animEndCurrentCnt = 0, animEndNextCnt = 0,
  // check function for the end of each animation
  isFinished = function() {
   ++cntAnims;
   if( cntAnims === 2 ) {
    self.isAnimating = false;
   }
  },
  // function for the end of the current item animation
  onEndAnimationCurrentItem = function() {
   ++animEndCurrentCnt;
   var endFn = function() {
    classie.removeClass( currentItem, 'hide' );
    classie.removeClass( currentItem, 'current' );
    isFinished();
   };

   if( !isSupported ) {
    endFn();
   }
   else if( animEndCurrentCnt === animElemsCurrentCount ) {
    currentItem.removeEventListener( animEndEventName, onEndAnimationCurrentItem );
    endFn();
   }
  },
  // function for the end of the next item animation
  onEndAnimationNextItem = function() {
   ++animEndNextCnt;
   var endFn = function() {
    classie.removeClass( nextItem, 'show' );
    classie.addClass( nextItem, 'current' );
    isFinished();
   };

   if( !isSupported ) {
    endFn();
   }
   else if( animEndNextCnt === animElemsNextCount ) {
    nextItem.removeEventListener( animEndEventName, onEndAnimationNextItem );
    endFn();
   }
  };

 if( isSupported ) {
  currentItem.addEventListener( animEndEventName, onEndAnimationCurrentItem );
  nextItem.addEventListener( animEndEventName, onEndAnimationNextItem );
 }
 else {
  onEndAnimationCurrentItem();
  onEndAnimationNextItem();
 }

 classie.addClass( currentItem, 'hide' );
 classie.addClass( nextItem, 'show' );
}


Password: www.duniadesain.net
Script ini bisa bekerja di ( IE9, Google Chrome 30+, Firefox 27+)

Dan itu dia! Kami harap Anda menikmati tutorial ini dan merasa berguna!
Perhatikan bahwa IE11 tetap tidak mendukung gaya transform: preserve-3d, sehingga fallback akan ditampilkan disana.
Source:

Comments

Popular posts from this blog

Cara Custom Gaya Form File Upload

Navigasi Button Untuk SlideShow

Transisi untuk Menu Off-Canvas