收藏
回答

swiper 嵌套video视频不能全屏展示的问题?

API组件名称:swiper,swiper-item,video

微信版本号:Version 8.0.7

基础库版本号:2.8.0

测试机型:iPhone XR、HUAWEIP40

问题代码如下:

wxml代码

<!--pages/tab/browse/index.wxml-->
<view class="browse">
  <swiper class="swiper-box" duration="300" circular="{{circular}}" current="{{current}}" vertical="{{true}}" bindanimationfinish="swiperChange" bindtap="tabVideo">
    <swiper-item wx:if="{{videoObjList[0].id}}" item-id="{{videoObjList[0].index}}">
      <video bindplay="eventPlay" id="video0" class="video-box" poster="{{videoObjList[0].videoLogo}}" src="{{videoObjList[0].videoUrl}}" object-fit="contain" loop="{{true}}" controls="{{false}}" show-progress="{{false}}" show-fullscreen-btn="{{false}}" show-play-btn="{{false}}"
        show-center-play-btn="{{false}}" enable-progress-gesture="{{false}}" vslide-gesture-in-fullscreen="{{false}}"></video>
    </swiper-item>
    <swiper-item wx:if="{{videoObjList[1].id}}" item-id="{{videoObjList[1].index}}">
      <video bindplay="eventPlay" id="video1" class="video-box" poster="{{videoObjList[1].videoLogo}}" src="{{videoObjList[1].videoUrl}}" object-fit="contain" loop="{{true}}" controls="{{false}}" show-progress="{{false}}" show-fullscreen-btn="{{false}}" show-play-btn="{{false}}"
        show-center-play-btn="{{false}}" enable-progress-gesture="{{false}}" vslide-gesture-in-fullscreen="{{false}}"></video>
    </swiper-item>
    <swiper-item wx:if="{{videoObjList[2].id}}" item-id="{{videoObjList[2].index}}">
      <video bindplay="eventPlay" id="video2" class="video-box" poster="{{videoObjList[2].videoLogo}}" src="{{videoObjList[2].videoUrl}}" object-fit="contain" loop="{{true}}" controls="{{false}}" show-progress="{{false}}" show-fullscreen-btn="{{false}}" show-play-btn="{{false}}"
        show-center-play-btn="{{false}}" enable-progress-gesture="{{false}}" vslide-gesture-in-fullscreen="{{false}}"></video>
    </swiper-item>
  </swiper>


  <!-- 播放按钮 -->
  <view class="videoLogo flex flex-alignItems flex-justifyCenter" wx:if="{{playStatus}}" bindtap="tabVideo">
    <image class="play" src="https://jxtt-h5-1258058953.cos.ap-guangzhou.myqcloud.com/images/videoplay_btn.png"></image>
  </view>


  <!-- 用户 头像 名称 关注 地址 -->
  <view class="user flex flex-alignItems">
    <!-- 头像 -->
    <view class="head">
      <image src="{{videoInfo.userLogo}}" class="head-pic"></image>
    </view>
    <view class="user-rf">
      <!-- 名称 -->
      <view class="name hide1">
        {{videoInfo.userName}}
      </view>
      <!-- 地址 -->
      <view class="site flex flex-alignItems">
        <image src="https://jxtt-h5-1258058953.cos.ap-guangzhou.myqcloud.com/images/weizhi.png" class="address"></image>
        <view class="site-child hide1">{{videoInfo.address}}</view>
      </view>
    </view>
  </view>


  <view class="icon-box">
    <!-- 点赞 -->
    <view class="icon-list">
      <image class="dianzan" src="https://jxtt-h5-1258058953.cos.ap-guangzhou.myqcloud.com/images/videoPlayH5/video_like_praise.png" wx:if="{{videoInfo.isLike!=2}}"></image>
      <image class="dianzan" src="https://jxtt-h5-1258058953.cos.ap-guangzhou.myqcloud.com/images/videoPlayH5/video_info_praise.png" wx:else></image>
      <view>{{videoInfo.likeCount>0?videoInfo.likeCount:'点赞'}}</view>
    </view>


    <!-- 评论 -->
    <view class="icon-list">
      <image class="pinglun" src="https://jxtt-h5-1258058953.cos.ap-guangzhou.myqcloud.com/images/videoPlayH5/video_info_comments.png" mode=""></image>
      <view class="font-list">{{videoInfo.commentNum>0?videoInfo.commentNum:'评论'}}</view>
    </view>


    <!-- 分享 -->
    <button class="icon-list" open-type="share">
      <image class="fenxiang" src="https://jxtt-h5-1258058953.cos.ap-guangzhou.myqcloud.com/images/videoPlayH5/video_info_share.png"></image>
      <view>转发</view>
    </button>
  </view>


  <!-- 说明 -->
  <view class="tag hide2">
    {{videoInfo.videoExplain}}
  </view>
</view>

css代码:

.browse {
  width100vw;
  height100vh;
  position: relative;
  color#FFFFFF;
}


.browse .title {
  position: absolute;
  left0;
  top0;
  width100vw;
  font-size38rpx;
  z-index20;
  color#FFFFFF;
  display: flex;
  align-items: center;
  justify-content: center;
}


.browse .swiper-box {
  width100vw;
  height100vh;
  background#000000;
}


.browse .swiper-box .video-box {
  width100vw;
  height100vh;
}


.browse .videoLogo {
  width100vw;
  height100vh;
  position: fixed;
  backgroundrgba(0000.3);
  left0;
  top0;
  z-index10;
  pointer-events: none;
}


.browse .videoLogo .play {
  width128rpx;
  height128rpx;
}


.browse .icon-box {
  position: fixed;
  right30rpx;
  bottom80rpx;
  z-index13;
  text-align: center;
  font-size24rpx;
}


.browse .icon-box .icon-list {
  width64rpx;
  padding0;
  backgroundrgba(0000);
  border: none;
  box-shadow: none;
  line-height1.4;
  color#fff;
  font-size24rpx;
  margin-top40rpx;
  position: relative;
}


.browse .icon-box .icon-list:after {
  border: none;
}


.browse .icon-box .icon-list .icon-text {
  position: absolute;
  transformtranslate(-50%, -50%);
  left50%;
  bottom: -20rpx;
  text-align: center;
  width100rpx;
}


.browse .icon-box .icon-list .dianzan {
  width60rpx;
  height60rpx;
}


.browse .icon-box .icon-list .pinglun {
  width64rpx;
  height64rpx;
}


.browse .icon-box .icon-list .fenxiang {
  width61rpx;
  height58rpx;
}


.browse .icon-box .icon-list .font-list {
  font-size24rpx;
  height32rpx;
}


.browse .user {
  border-radius48rpx;
  height90rpx;
  position: fixed;
  bottom180rpx;
  left30rpx;
  z-index13;
  font-size30rpx;
}
.browse .user .head {
  width90rpx;
  height90rpx;
  border-radius50%;
  position: relative;
  background#dedede;
}
.browse .user .head .head-pic {
  width90rpx;
  height90rpx;
  display: block;
  border-radius50%;
}
.browse .user .name {
  max-width400rpx;
  font-size32rpx;
  padding-right20rpx;
  padding-left18rpx;
}
.browse .user .site {
  font-size24rpx;
  padding-top4rpx;
  padding-left18rpx;
}


.browse .user .site .address {
  width24rpx;
  height26rpx;
  margin-right10rpx;
  display: inline-block;
}


.browse .user .site .site-child {
  max-width500rpx;
}


.browse .tag {
  position: fixed;
  bottom100rpx;
  left30rpx;
  z-index13;
  font-size26rpx;
  width570rpx;
}


js代码

videoList.js

export const defaultVideo1 = [{
  "id": 5956,
  "userName": "深圳测试店铺0",
  "userLogo": "https://dgtest.oss-cn-shenzhen.aliyuncs.com/mall/upfile/mypro/5dfc435e67135.jpg",
  "videoLogo": "",
  "videoUrl": "https://jxtt.diangoumall.com/149c30b0vodcq1258058953/40b6435b5285890787971623627/y06TVrVzF04A.mp4",
  "videoExplain": "站着不费劲",
  "commentNum": 118,
  "likeCount": 132,
  "isLike": 2,
  "address": "天津市市辖区和平区五大道街道0",
},
{
  "id": 5957,
  "userName": "深圳测试店铺1",
  "userLogo": "https://dgtest.oss-cn-shenzhen.aliyuncs.com/mall/upfile/mypro/5dfc435e67135.jpg",
  "videoLogo": "",
  "videoUrl": "https://jxtt.diangoumall.com/149c30b0vodcq1258058953/5cf8ad5e5285890789407752595/isJH35npzgcA.mp4",
  "videoExplain": "站着不费劲",
  "commentNum": 16,
  "likeCount": 8989,
  "isLike": 2,
  "address": "天津市市辖区和平区五大道街道1",
},
{
  "id": 5958,
  "userName": "深圳测试店铺2",
  "userLogo": "",
  "videoLogo": "",
  "videoUrl": "https://jxtt.diangoumall.com/149c30b0vodcq1258058953/b0e0331e5285890787280665379/pnY2cIn027sA.mp4",
  "videoExplain": "站着不费劲",
  "commentNum": 10,
  "likeCount": 111,
  "isLike": 2,
  "address": "天津市市辖区和平区五大道街道2",
}
]


export const defaultVideo2 = [{
  "id": 5959,
  "userName": "深圳测试店铺3",
  "userLogo": "",
  "videoLogo": "",
  "videoUrl": "https://jxtt.diangoumall.com/149c30b0vodcq1258058953/e7b3c9305285890787314800448/sVG80ijk0MYA.mp4",
  "videoExplain": "站着不费劲",
  "commentNum": 1668,
  "likeCount": 269,
  "isLike": 2,
  "address": "天津市市辖区和平区五大道街道3",
}, {
  "id": 59523,
  "userName": "深圳测试店铺3",
  "userLogo": "",
  "videoLogo": "",
  "videoUrl": "https://jxtt.diangoumall.com/149c30b0vodcq1258058953/1b9f6d7c5285890789444285546/GrxKyjdizyIA.mp4",
  "videoExplain": "站着不费劲",
  "commentNum": 1668,
  "likeCount": 269,
  "isLike": 2,
  "address": "天津市市辖区和平区五大道街道3",
}, {
  "id": 59555,
  "userName": "深圳测试店铺3",
  "userLogo": "",
  "videoLogo": "",
  "videoUrl": "https://jxtt.diangoumall.com/149c30b0vodcq1258058953/572576c65285890789421030226/RIpAqaa96KsA.mp4",
  "videoExplain": "站着不费劲",
  "commentNum": 1668,
  "likeCount": 269,
  "isLike": 2,
  "address": "天津市市辖区和平区五大道街道3",
},]

import { defaultVideo1, defaultVideo2} from "./mock/videoList.js"
const app = getApp()


Page({
  data: {
    circular: false,
    // 当前播放视频的数据
    videoInfo: {
      index: 0,
    },
    // 滑块
    current: 0,
    // 播放状态
    playStatus: false,
    videoObjList: {
      0: {},
      1: {},
      2: {},
    },
    paging: {
      page: 1,
      size: 9
    }
  },
  onShow() {


  },
  onLoad(e) {
    this.pageStatus = 0 // 页面初始化状态
    this.videoKey = "video" // 视频id key
    this.videoList = [] // 渲染的视频
    this.residueVideoList = [] // 取余的数组
    this.videoIndex = 0 // 当前视频的位置
    this.loadingVideo = 0


  },
  onReady() {
    this.videoObj0 = this.getVideoObj(this.videoKey, 0)
    this.videoObj1 = this.getVideoObj(this.videoKey, 1)
    this.videoObj2 = this.getVideoObj(this.videoKey, 2)


    // 获取视频列表
    this.getVideoList()
  },
  // 获取视频列表
  getVideoList() {
    setTimeout(() => {
      let oldVideoLength = this.videoList.length


      // 这段模拟异步数据的获取
      let pageList = []
      if (this.data.paging.page == 1) {
        pageList = defaultVideo1
      } else if (this.data.paging.page == 2) {
        pageList = defaultVideo2
      } else {
        pageList = []
      }
      console.log(this.data.paging.page)
      console.log(pageList)
      console.log(this.residueVideoList)


      pageList = pageList.map(v => {
        // v.videoUrl = ase.decrypt(v.videoUrl || "") // 视频链接加密 防止链接被盗用


        return v
      })


      // 无数据的情况
      if (pageList.length < 1 && this.data.paging.page == 1) {
        return
      }


      // 如果数据少于1重新拿分页为1的数据
      if (pageList.length < 1 && this.data.paging.page != 1) {
        this.setData({
          ['paging.page']: 1,
        })
        this.getVideoList()
        return
      }


      // 滑块数量
      let itemNumber = Object.keys(this.data.videoObjList).length || 3


      // 重新计算数组的排列
      const videoData = this.formArrayVideo(this.videoList, this.residueVideoList, pageList, itemNumber)


      // 渲染的数组
      this.videoList = videoData.list.map((v, index) => {
        return {
          ...v,
          index
        }
      })


      // 取余的数组
      this.residueVideoList = videoData.residue


      // 避免去重后数据保持不变产生死循环
      if (oldVideoLength != this.videoList.length) {
        this.setData({
          circular: true,
        })


        // 开始渲染
        this.lazyVideo()
      }


      // 第一次播放
      if (this.pageStatus == 0) {


        // 第一次初始化加载完毕
        this.pageStatus = 1


        // 滑块位置
        const current = this.data.current


        // 开始播放
        this.currentPlay(current, current)


      }


      this.setData({
        ['paging.page']: this.data.paging.page + 1,
      })


    }, 300)
  },
  // swiper切换
  swiperChange(e) {
    if (e.detail.source == "touch") {
      // 旧的滑块位置
      const oldCurrent = this.data.current
      // 当前滑块的位置
      const current = e.detail.current
      if (oldCurrent == current) return;


      this.setData({
        current
      })


      // 当前视频在列表中的索引
      this.videoIndex = parseInt(e.detail.currentItemId)
      console.log(this.videoIndex)


      // 开始渲染
      this.lazyVideo()


      // 开始播放
      this.currentPlay(oldCurrent, current)
    }
  },
  // 加载视频
  lazyVideo() {


    const videoList = this.videoList // 渲染的数组
    const videoIndex = this.videoIndex // 当前播放的视频在数组里的索引
    const current = this.data.current // 滑块位置


    const lastVideo = videoList[videoIndex - 1] || {}
    const lastTwoVideo = videoList[videoIndex - 2] || {}
    const nowVideo = videoList[videoIndex] || {}
    const nextVideo = videoList[videoIndex + 1] || {}
    const nextTwoVideo = videoList[videoIndex + 2] || {}


    if (videoIndex == 0) {
      this.setData({
        circular: false,
        ['videoObjList.0']: nowVideo,
        ['videoObjList.1']: nextVideo,
        ['videoObjList.2']: nextTwoVideo,
      })
    } else if (videoIndex == videoList.length - 1) {
      console.log('滑动到了最后一页')
      this.setData({
        circular: false,
        ['videoObjList.0']: lastTwoVideo,
        ['videoObjList.1']: lastVideo,
        ['videoObjList.2']: nowVideo,
      })
      // 获取视频列表
      this.getVideoList()
    } else {
      if (current == 0) {
        this.setData({
          circular: true,
          ['videoObjList.0']: nowVideo,
          ['videoObjList.1']: nextVideo,
          ['videoObjList.2']: lastVideo,
        })
      }
      if (current == 1) {
        this.setData({
          circular: true,
          ['videoObjList.0']: lastVideo,
          ['videoObjList.1']: nowVideo,
          ['videoObjList.2']: nextVideo,
        })
      }
      if (current == 2) {
        this.setData({
          circular: true,
          ['videoObjList.0']: nextVideo,
          ['videoObjList.1']: lastVideo,
          ['videoObjList.2']: nowVideo,
        })
      }
    }


    this.setData({
      videoInfo: nowVideo
    })
  },
  // 播放视频的逻辑
  currentPlay(oldCurrent, current) {
    // 获取上一个视频实例
    const oldVideoObj = this.getVideoObj(this.videoKey, oldCurrent)


    // 暂停上一个视频实例
    this.pauseVideo(oldVideoObj)


    // 获取当前视频实例
    const videoObj = this.getVideoObj(this.videoKey, current)


    // 播放当前视频实例
    this.playVideo(videoObj)
  },
  // 播放/或暂停视频
  tabVideo() {
    let playStatus = this.data.playStatus
    let current = this.data.current
    // 获取当前视频实例
    const videoObj = this.getVideoObj(this.videoKey, current)


    if (!playStatus) {
      // 播放停视频实例
      this.pauseVideo(videoObj)
    } else {
      // 播放当前视频实例
      this.playVideo(videoObj)
    }
    this.setData({
      playStatus: !playStatus
    })
  },
  // 视频开始播放
  eventPlay() {
    this.setData({
      playStatus: false
    })
  },
  // 播放视频
  playVideo(videoObj) {
    videoObj && videoObj.play()
  },
  // 暂停视频
  pauseVideo(videoObj) {
    videoObj && videoObj.pause()
  },
  // 销毁实例
  deleteVideoObJ(videoObj) {
    videoObj && videoObj.stop()
  },
  // 获取视频实例
  getVideoObj(key, index) {
    return wx.createVideoContext(key + index)
  },
  // 格式化数组取渲染数组及余数组
  formArrayVideo(oldList = [], residueList = [], newlist = [], itemNumber = 3) {
    // 原数组
    let onwList = oldList.concat(residueList, newlist)
    // 倍数
    const ints = Math.floor(onwList.length / itemNumber)
    // 最新数组
    const list = onwList.slice(0, ints * itemNumber) || []
    // 缓存余下的数组
    const residue = onwList.slice(ints * itemNumber, onwList.length) || []


    if (list.length < 1) {
      return {
        list: onwList,
        residue: [],
      }
    } else {
      return {
        list,
        residue,
      }
    }
  }
})

综上述代码直接放在小程序开发工具,就可以运行。

问题所在:

  1. 在 “微信开发者工具” 使用iphone6 7运行是正常的。如果使用iPhone XR运行就会出现黑边。不能全屏的问题。
  2. json文件设置如下
"navigationStyle": "custom",
"navigationBarTextStyle":"white",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundTextStyle": "light"

运行效果图如下:iPhone XR

运行效果图如下:iPhone 6 7


回答关注问题邀请回答
收藏

1 个回答

登录 后发表内容