swiper 实现 带video的banner

2020-11-12  本文已影响0人  八妹sss

遇到的问题:

1、swiper复制的节点点击事件失效问题
2、多个视频同时播放的问题
3、安卓手机上视频播放后轮播卡顿的问题

解决问题2问题3的思路:

页面展示用图片展示,点击播放视频时才显示video元素,当前换到下一个时,暂停上一个并隐藏video元素

解决方法见代码

<template>
  <div class="main">
    <div v-if="bannerList.length" class="banner-wrapper">
      <swiper :class="{single: bannerList.length === 1}" v-if='bannerList.length > 1' :options="swiperOption">
        <swiper-slide v-for='(banner, index) of bannerList' :key='"banner" + index'>
          <div class='banner-content'>
            <video
              v-if="banner.bannerVideo"
              :ref="`publicVideo${index}`"
              style="width: 100%; height: 100%; object-fit: fill"
              controls="controls"
              webkit-playsinline
              playsinline
              x5-playsinline
              :poster="banner.bannerImg"
              :src='banner.bannerVideo'>
              <source :src="banner.bannerVideo" type="video/mp4;"/>
            </video>
            <div v-if="banner.bannerVideo" class="play"></div>
            <img
              class='banner-img'
              :src="banner.bannerImg">
            <div class='banner-name'>{{banner.bannerName}}</div>
          </div>
        </swiper-slide>
      </swiper>
      <div class='banner-content' v-else>
        <video
          v-if="bannerList[0].type"
          :ref="`publicVideo${index}`"
          style="width: 100%; height: 100%; object-fit: fill"
          controls="controls"
          webkit-playsinline
          playsinline
          x5-playsinline
          :poster="bannerList[0].bannerImg"
          :src='bannerList[0].bannerImg'>
          <source :src="bannerList[0].bannerImg" type="video/mp4;"/>
        </video>
        <img
          v-else
          class='banner-img'
          :src="bannerList[0].bannerImg">
        <div v-if="bannerList[0].type" class="play"></div>
        <div class='banner-name'>{{bannerList[0].bannerName}}</div>
      </div>
    </div>
    <div class="mt-title">关于公司</div>
    <ul class="info-list">
      <li @click="onJump('companyIntroduce')" class="info-item">
        <div class="bg-right"></div>
        <div class="bg-tag">About Us</div>
        <div class="cont">
          <p class="title"></p>
          <p class="learn-more"><span>了解详情</span><span class="icon-arrow"></span></p>
        </div>
      </li>
      <li @click="onJump('listedProducts')" class="info-item">
        <div class="bg-right"></div>
        <div class="bg-tag">Product</div>
        <div class="cont">
          <p class="title"></p>
          <p class="learn-more"><span>了解详情</span><span class="icon-arrow"></span></p>
        </div>
      </li>
      <li @click="onJump('mainResearch')" class="info-item">
        <div class="bg-right"></div>
        <div class="bg-tag">Develop</div>
        <div class="cont">
          <p class="title"></p>
          <p class="learn-more"><span>了解详情</span><span class="icon-arrow"></span></p>
        </div>
      </li>
    </ul>
    <div class="contact-us">
      <div @click="onJump('contactWe')" class="cont">
        <p class="icon-contact"><img src="" alt=""></p>
        <p class="text">联系我们</p>
      </div>
    </div>
  </div>
</template>
<script>
import { swiper, swiperSlide } from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.css'
let vm = null
export default {
  components: {
    swiper,
    swiperSlide
  },
  data () {
    return {
      bannerList: [],
      swiperOption: {
        watchSlidesProgress: true,
        slidesPerView: 'auto',
        spaceBetween: 8,
        centeredSlides: true,
        observer: true,
        observeParents: true,
        loop: true,
        loopedSlides: 5,
        on: {
          // 解决复制的节点无法点击的问题
          click () {
            const realIndex = this.realIndex
            if (vm.bannerList[realIndex]) {
              // 视频播放
              if (vm.bannerList[realIndex].bannerVideo) {
                vm.showControls()
                // banner 跳转
              } else if (vm.bannerList[realIndex].jumpLink) {
                location.href = vm.bannerList[realIndex].jumpLink
              }
            }
          },
          // 控制slid缩放
          slideChangeTransitionStart: function () {
            vm.watchPlay() // 隐藏所有视频元素
            vm.pauseAll(this.realIndex) // 暂停播放的视频
          }
        }
      }
    }
  },
  methods: {
    // 获取banner
    fetchBanner () {
      this.$_load.show()
      let url = `${this.SERVICE_PORTAL}/${localStorage.getItem('appid')}/banner`
      this.$get(url).then(res => {
        this.$_load.hide()
        if (res.code === 200) {
          let data = res.data
          if (data) {
            this.bannerList = data
            if (this.bannerList.length > 2) {
              this.swiperOption.loop = true
              this.swiperOption.loopedSlides = 5
            } else {
              this.swiperOption.loop = false
              this.swiperOption.loopedSlides = 0
            }
            this.$nextTick(() => {
              this.watchPlay()
            })
          }
        }
      }).catch(() => {
        this.$_load.hide()
      })
    },
    // 点击蒙层播放视频
    showControls () {
      this.watchPlay()
      let dom = document.querySelector('.swiper-slide-active video')
      if (dom) {
        dom.style.display = 'block'
        document.querySelector('.swiper-slide-active .banner-img').style.display = 'none'
        document.querySelector('.swiper-slide-active .play').style.display = 'none'
        dom.controls = false
        dom.play()
        setTimeout(() => {
          dom.controls = true
        }, 0)
      }
    },
    // 监听所有视频的播放事件并暂停
    watchPlay () {
      // 隐藏所有的video标签
      let videoAllDom = document.querySelectorAll('video')
      let playAllDom = document.querySelectorAll('.play')
      let imgAllDom = document.querySelectorAll('.banner-img')
      let self = this
      for (let i = 0; i < imgAllDom.length; i++) {
        imgAllDom[i].style.display = 'block'
      }
      for (let i = 0; i < videoAllDom.length; i++) {
        (function () {
          var p = i
          videoAllDom[p].style.display = 'none'
          playAllDom[p].style.display = 'block'
          videoAllDom[p].addEventListener('play', () => {
            self.pauseAll(p)
          })
        })()
      }
    },
    // 暂停所有视频
    pauseAll (index) {
      let videoAllDom = document.querySelectorAll('video')
      for (var j = videoAllDom.length - 1; j >= 0; j--) {
        if (j !== index) videoAllDom[j].pause()
      }
    },
    onJump (routeName) {
      if (routeName === 'listedProducts') {
        this.linkTo(routeName, {}, { type: 'al' })
      } else {
        this.linkTo(routeName)
      }
    }
  },
  created () {
    vm = this
    this.fetchBanner()
  }
}
</script>
<style lang="stylus" scoped>
.main
  width 100%
  max-width 750px
  margin 0 auto
  min-height 100vh
  background #fff
  padding-bottom 40px
  box-sizing border-box
  .banner-wrapper
    width 100%
    padding 18px 0px 16px
    box-sizing border-box
    // 单张时
    .single
      >>> .swiper-container
        height auto
      >>> .swiper-slide
        width 100%
    >>> .swiper-container
      height 185px
    >>> .swiper-slide
      width 91%
      &.swiper-slide-active
        opacity 1 !important
      &.swiper-slide-next
      &.swiper-slide-prev
        opacity 0.8 !important
  .banner-content
    height 100%
    position relative
    border-radius 4px
    overflow hidden
    font-size 0
    video
      width 100%
      height 100%
      display none
    .banner-img
      display block
      width 100%
      height 100%
    .play
      width 100%
      height 100%
      background rgba(0, 0, 0, 0.06) url('~assets/img/home_ic_play@3x.png') no-repeat center / 45px
      border-radius 4px
      position absolute
      top 50%
      left 50%
      transform translate(-50%, -50%)
      z-index 1
    .banner-name
      position absolute
      bottom 6px
      left 0
      right 0
      background url('~assets/img/ic_biaoti@3x.png') no-repeat left center/ 292px 29px
      color #fff
      padding 0 36px 0 10px
      font-size 15px
      font-weight 500
      line-height 21px
      noWrap()
      z-index 2
  .mt-title
    width 100%
    padding 0 16px
    line-height 22px
    font-size 18px
    font-family 'PingFangSC-Semibold', 'PingFang SC'
    font-weight 700
    color #333333
    margin-top 13px
  .info-list
    width 100%
    padding 0 16px
    margin-top 13px
    .info-item
      width 100%
      height 96px
      border-radius 6px
      box-shadow 0px 0px 6px 0px rgba(0, 0, 0, 0.08)
      position relative
      & + .info-item
        margin-top 20px
      .bg-right
        width 90px
        height 90px
        position absolute
        right 25px
        top 50%
        transform translate(0, -50%)
      .bg-tag
        font-size 32px
        font-family 'PingFangSC-Semibold', 'PingFang SC'
        font-weight 700
        color #EAEAEA
        position absolute
        top 20px
        left 35px
        z-index 1
      .cont
        width 100%
        height 100%
        padding 30px 156px 0 34px
        box-sizing border-box
        position absolute
        top 50%
        left 50%
        transform translate(-50%, -50%)
        z-index 2
        .learn-more
          display flex
          align-items center
          font-size 14px
          font-family 'PingFangSC-Regular', 'PingFang SC'
          font-weight 400
          color #333333
          line-height 18px
          margin-top 5px
          .icon-arrow
            display inline-block
            width 11px
            height 11px
            background url('~assets/img/home_ic_more@3x.png') no-repeat center / 100%
            margin-left 3px
      &:nth-of-type(1)
        background #fff url('~assets/img/gongsijieshao@3x.png') no-repeat left center / 114px 96px
        .bg-right
          background url('~assets/img/home_ic_gongsijieshao@3x.png') no-repeat center / 90px
        .cont
          .title
            width 82px
            height 20px
            background url('~assets/img/tex_gongsi@3x.png') no-repeat center / 100%
      &:nth-of-type(2)
        background #fff url('~assets/img/chanpin@3x.png') no-repeat left center / 114px 96px
        .bg-right
          background url('~assets/img/home_ic_chanpin@3x.png') no-repeat center / 90px
        .bg-tag
          top 22px
        .cont
          padding 32px
          .title
            width 102px
            height 20px
            background url('~assets/img/tex_chanpin@3x.png') no-repeat center / 100%
      &:nth-of-type(3)
        background #fff url('~assets/img/zaiyanchanpin@3x.png') no-repeat left center / 114px 96px
        .bg-right
          background url('~assets/img/home_ic_zaiyanchanpin@3x.png') no-repeat center / 90px
        .bg-tag
          top 23px
        .cont
          padding-top 33px
          .title
            width 123px
            height 20px
            background url('~assets/img/tex_zaiyanchanpin@3x.png') no-repeat center / 100%
  .contact-us
    display flex
    justify-content flex-end
    padding-right 15px
    margin-top 28px
    .cont
      display flex
      flex-direction column
      align-items center
      .icon-contact
        width 54px
        height 54px
        background url('~assets/img/home_ic_lianxi@3x.png') no-repeat center / 100%
      .text
        line-height 16px
        font-size 12px
        font-family 'PingFangSC-Medium', 'PingFang SC'
        font-weight 500
        color #333333
</style>
上一篇下一篇

猜你喜欢

热点阅读