用Vue-Awesome-Swiper實現旋轉疊加輪播效果&平移輪播效果

實現效果

  • 旋轉疊加 javascript

    旋轉疊加效果

  • 平移 css

    旋轉疊加效果效果

前段時間作Hybrid App,UI設計溼要求某一個頁面的展現要實現滑動輪播效果,選中的內容卡片居中顯示,上一個內容卡片和下一個內容以小一倍的大小顯示在選中的卡片後頭,並且要高斯模糊等等。。最騷的是滑動特效要是一個個旋轉疊加。(摔!vue

當時用的是vue-cli-3 + ant-design-vue實現的頁面,發現ant-design-vue裏頭有現成的Carousel組件可用,因爲排期比較急,先暫時用這個實現了初版,沒有特效沒有其餘花裏胡哨的展現。驗收完初版後,發現ant-design-vue的坑是真的多啊。。Carousel在移動端也是十分的不流暢。老是就是體驗特別的很差。最後一氣之下,所有樣式本身寫,所有組件本身封裝,將ant-design-vue完完整整移出了項目。java

輪播圖這塊想到了Swiper這一好東西,如今已經有了vue版,可是是沒有專門的vue版文檔的,能夠找到的項目也比較少。無奈之下啃了Swiper4文檔,一頓猛操做,摸到了一點點門道。把需求實現了是也。簡單整理了一下,寫了個簡單的小demo,記錄一下,若是能夠幫到你那是最好啦~git

1.首先引入Vue-Awesome-Swiper

引入Vue-Awesome-Swiper有兩種方式,一種是全局引入,一種是組件內引入。若是你的項目裏只有一個地方要用到這玩意,那就在用到的那個頁面引入就行,若是多個地方要用到,那就全局引入吧。github

  • 全局引入:
// main.js
import VueAwesomeSwiper from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.css'

Vue.use(VueAwesomeSwiper, /* { default global options } */)
複製代碼
  • 組件內引入:
// xxx.vue
<script>
import 'swiper/dist/css/swiper.css'
import { swiper, swiperSlide } from 'vue-awesome-swiper'

export default {
  components: {
    swiper,
    swiperSlide
  }
}
</script>
複製代碼

2.在頁面使用

<template>
  <div class="swiper-content">
    <swiper ref="mySwiper" :options="swiperOption" class="show-swiper">
      <template v-for="(item, index) in list">
        <swiper-slide :key="index">
          <div class="swiper-item">
            <span>{{ item }}</span>
          </div>
        </swiper-slide>
      </template>
    </swiper>
  </div>
</template>
複製代碼

js部分vuex

  • 旋轉疊加
<script>
import { mapState } from 'vuex'
import store from '@/store'
export default {
  data() {
    return {
      list: [1, 2, 3, 4, 5, 6],
      swiperOption: {
        // 設置slider容器可以同時顯示的slides數量,默認爲1, 'auto'則自動根據slides的寬度來設定數量
        slidesPerView: 'auto',
        /*
        * 開啓這個參數來計算每一個slide的progress(進度、進程)
        * 對於slide的progress屬性,活動的那個爲0,其餘的依次減1
        */
        watchSlidesProgress: true,
        // 默認active slide居左,設置爲true後居中
        centeredSlides: true,
        // 當你建立一個Swiper實例時是否當即初始化,這裏咱們手動初始化
        init: false,
        on: {
          progress: function() {
            for (let i = 0; i < this.slides.length; i++) {
              const slide = this.slides.eq(i) // 指定匹配元素集縮減值
              const slideProgress = this.slides[i].progress // 當前元素集的progress值

              let modify = 0 // 偏移權重
              if (parseInt(Math.abs(slideProgress)) > 0) {
                modify = Math.abs(slideProgress) * 0.2 // 不必定要0.2,可自行調整
              }
              const translate = slideProgress * modify * 500 + 'px' // 500是swiper-slide的寬度
              const scale = 1 - Math.abs(slideProgress) / 5 // 縮放權重值,隨着progress由中向兩邊依次遞減,可自行調整
              const zIndex = 99 - Math.abs(Math.round(10 * slideProgress))
              slide.transform(`translateX(${translate}) scale(${scale})`)
              slide.css('zIndex', zIndex)
              slide.css('opacity', 1) // 是否可見
              if (parseInt(Math.abs(slideProgress)) > 1) { // 設置了只有選中的元素以及他兩遍的顯示,其餘隱藏
                slide.css('opacity', 0)
              }
            }
          },
          slideChange: function() {
            store.commit('SET_ACTIVE_INDEX', this.activeIndex)
          }
        }
      }
    }
  },
  computed: {
    swiper() {
      return this.$refs.mySwiper.swiper
    },
    ...mapState({
      activeItemIndex: state => state.activeIndex
    })
  },
  mounted() {
    this.initSwiper()
  },
  methods: {
    initSwiper() {
      this.$nextTick(async() => {
        await this.swiper.init() // 如今才初始化
        await this.swiper.slideTo(this.activeItemIndex)
      })
    }
  }
}
</script>
複製代碼
  • 平移
<script>
import { mapState } from 'vuex'
import store from '@/store'
export default {
  data() {
    return {
      list: [1, 2, 3, 4, 5, 6],
      swiperOption: {
        slidesPerView: 'auto',
        watchSlidesProgress: true,
        // 設定slide與左邊框的預設偏移量(單位px)
        slidesOffsetBefore: 37,
        // 設置slide之間的距離(單位px)
        spaceBetween: 17,
        centeredSlides: true,
        init: false,
        on: {
          progress: function() {
            for (let i = 0; i < this.slides.length; i++) {
              const slide = this.slides.eq(i)
              const slideProgress = this.slides[i].progress

              const scale = 1 - Math.abs(slideProgress) / 5 // 縮放權重值,隨着progress由中向兩邊依次遞減,可自行調整
              slide.transform(`scale3d(${scale}, ${scale}, 1)`)
            }
          },
          slideChange: function() {
            store.commit('SET_ACTIVE_INDEX', this.activeIndex)
          }
        }
      }
    }
  },
  computed: {
    swiper() {
      return this.$refs.mySwiper.swiper
    },
    ...mapState({
      activeItemIndex: state => state.activeIndex
    })
  },
  mounted() {
    this.initSwiper()
  },
  methods: {
    initSwiper() {
      this.$nextTick(async() => {
        await this.swiper.init() // 如今才初始化
        await this.swiper.slideTo(this.activeItemIndex)
      })
    }
  }
}
</script>
複製代碼

配置參數那裏,init我是設置的false,我是想在項目掛載完成後,獲取到了接口數據以後,再用this.swiper.init()去初始化輪播組件的,而後我把激活項的索引存在了vuex裏頭,這樣每次從其餘頁面返回這個頁面,就能夠用this.swiper.slideTo(this.activeItemIndex)去控制我要定位到哪個內容卡片先。vue-cli

3.樣式初始化方面

.swiper-content {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
  margin: 0 auto;
  padding: 50px 0;

  .show-swiper {
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;

    .swiper-slide {
      width: 500px;
      // 表示全部屬性都有動做效果,過分時間爲0.4s,以慢速開始和結束的過渡效果
      transition: all .4s cubic-bezier(.4, 0, .2, 1);
      
      .swiper-item {
        width: 100%;
        height: 500px;
        background: rgb(140, 172, 134);
        border-radius: 6px;
        color: orangered;
        font-size: 24px;
        line-height: 1.5;
        border: 1px solid orangered;
      }
    }
  }
}
複製代碼

由於slidesPerView: 'auto',因此swiper-slide咱們要給他一個初始化的寬度,以便他自動計算容器寬度,而後這裏我設置了動畫的效果transition: all .4s cubic-bezier(.4, 0, .2, 1);能夠根據本身的須要做出改動less

大概就是這些內容,是否是很簡單呢。我會把源碼地址貼出來,有須要的話就自行clone參考吧~,項目裏我使用的是vue-cli3,能夠自行調整。async

相關文章
相關標籤/搜索