swiper-vertical-video.uvue 8.4 KB
Newer Older
1
<template>
雪洛's avatar
雪洛 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  <view class="page">
    <view @click="back" class="nav-back">
      <image class="back-img" src="/static/template/scroll-fold-nav/back.png" mode="widthFix"></image>
    </view>
    <swiper class="swiper" :current="current" :circular="index != 0" :vertical="true" @change="onSwiperChange"
      @transition="onTransition">
      <swiper-item class="swiper-item" v-for="(item,i) in visibleList" :key="i">
        <video @click="changeState(i)" ref="video" class="video-box" objectFit="cover" :id="'video-'+i"
          @loadstart="onLoadstart(i)" :src="item.src" :poster="item.poster_src" :autoplay="false"
          :show-center-play-btn="false" :loop="true" @play="onPlay(i)" @pause="onPause(i)"></video>
        <view class="video-cover" @click="changeState(i)">
          <image v-if="state[i] === 'pause'" class="play-btn" src="/static/template/swiper-vertical-video/play.png"
            mode="widthFix"></image>
        </view>
        <view class="video-info" v-if="0">
          <text class="video-info-text">容器:第 {{i}} 个</text>
          <text class="video-info-text">内容:{{item.content}}</text>
        </view>
      </swiper-item>
    </swiper>
    <view class="debug-info" v-if="0">
23 24 25
      <text class="status-text">debug-info 播放状态:</text>
      <text class="status-text" v-for="(value,index) in state">第{{index+1}}个:{{ value }}</text>
    </view>
雪洛's avatar
雪洛 已提交
26
  </view>
27 28
</template>
<script>
雪洛's avatar
雪洛 已提交
29 30 31
  type ListItem = { _id : string, content : string, src : string, poster_src : string }
  let page : number = 0,
    currentPageIsShow : boolean = true;
32

雪洛's avatar
雪洛 已提交
33 34 35 36
  export default {
    components: {},
    data() {
      return {
雪洛's avatar
雪洛 已提交
37
        $videoContextMap: new Map<string, VideoContext>(),
雪洛's avatar
雪洛 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
        list: [] as ListItem[],
        visibleList: [] as ListItem[],// 提高性能 可见的只有3个
        current: 0 as number,
        index: 0,
        state: ["unPlay", "unPlay", "unPlay"] as string[]
      }
    },
    created() {
      this.list = this.getData()
      this.visibleList = this.list.slice(0, 3)
    },
    watch: {
      current(current : number, oldCurrent : number) {
        let changeNumber = current - oldCurrent
        if (changeNumber == 1 || changeNumber == -2) {
          // console.error('向右');
          this.index++
        } else {
          // console.error('向左');
          this.index--
        }
        // //翻页(3项为一页)
        if (Math.abs(changeNumber) == 2) {
          // console.log('翻页');
          page = Math.floor(this.index / 3);
          // console.log(this.index);
          // console.log('page',page);
          // console.log('slice',3*page,3*page+3);
          if (this.list.length < 3 * page + 3) {
            let list : ListItem[] = this.getData()
            this.list.push(...list)
          }
70

雪洛's avatar
雪洛 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
          let visibleList = this.list.slice(3 * page, 3 * page + 3)
          // 换数据
          this.visibleList = visibleList
        }

        this.state.forEach((_ : string, index : number) => {
          if (index === current) {
            this.doPlay(current)
          } else {
            // 除了选中的其他已经播放的都需要停止
            this.doStop(index)
            console.log('index:' + index + '已被执行停止');
          }
        })
      }
    },
    onReady() {
      // 一启动完成,就播放第一个
      this.doPlay(0)
    },
    onShow() {
      currentPageIsShow = true
    },
    onHide() {
      currentPageIsShow = false
      console.log('pages-onHide');
      this.doPause(this.current)
98
    },
雪洛's avatar
雪洛 已提交
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    onUnload() {
      this.doPause(this.current)
    },
    methods: {
      changeState(index : number) {
        if (this.state[index] === 'play') {
          this.doPause(index)
        } else {
          this.doPlay(this.current)
        }
      },
      onLoadstart(index : number) {
        console.error("onLoadstart  video" + index);
      },
      getVideoContext(index : number) : VideoContext {
        const videoContextMap = this.$data['$videoContextMap'] as Map<string, VideoContext>
        let videoContext : VideoContext | null = videoContextMap['video-' + index]
        if (videoContext == null) {
          videoContext = uni.createVideoContext('video-' + index, this) as VideoContext
          videoContextMap['video-' + index] = videoContext
        }
        return videoContext
121
      },
雪洛's avatar
雪洛 已提交
122 123 124
      doPlay(index : number) {
        console.log("doPlay  video" + index);
        this.getVideoContext(index).play()
125
      },
雪洛's avatar
雪洛 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
      doStop(index : number) {
        console.log("doStop  video-" + index);
        this.getVideoContext(index).stop();
        // TODO 临时方案:解决.stop()时触发了doPause的问题
        setTimeout(() => {
          this.state[index] = 'unPlay'
        }, 1000)
      },
      doPause(index : number) {
        this.getVideoContext(index).pause()
        console.log("doPause  video-" + index);
      },
      onPause(index : number) {
        this.state[index] = 'pause'
        console.log('onPause', index);
      },
      onPlay(index : number) {
        if (this.current != index || !currentPageIsShow) {
          this.onPause(index)
        } else {
          this.state[index] = 'play'
          console.log('onPlay', index);
148
        }
雪洛's avatar
雪洛 已提交
149 150 151 152 153 154 155
      },
      getData() : ListItem[] {
        let videoUrlList = [
          'https://qiniu-web-assets.dcloud.net.cn/uni-app-x/static/video/swiper-vertical-video/uts.mp4',
          'https://qiniu-web-assets.dcloud.net.cn/uni-app-x/static/video/swiper-vertical-video/uni-ai.mp4',
          'https://qiniu-web-assets.dcloud.net.cn/uni-app-x/static/video/swiper-vertical-video/uni-verify.mp4'
        ] as string[]
156

雪洛's avatar
雪洛 已提交
157 158 159 160 161
        let posterSrcList = [
          'https://qiniu-web-assets.dcloud.net.cn/uni-app-x/static/images/swiper-vertical-video-poster/uni-uts.jpg',
          'https://qiniu-web-assets.dcloud.net.cn/uni-app-x/static/images/swiper-vertical-video-poster/uni-ai.jpg',
          'https://qiniu-web-assets.dcloud.net.cn/uni-app-x/static/images/swiper-vertical-video-poster/uni-verify.jpg'
        ] as string[]
162

雪洛's avatar
雪洛 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
        let list = [] as ListItem[];
        for (let i = 0; i < 6; i++) {
          let index = this.list.length + i;
          let listItem : ListItem = {
            "_id": "a00" + index,
            "content": "这是第" + index + "条数据,url地址" + videoUrlList[i % 3],
            "src": videoUrlList[i % 3],
            "poster_src": posterSrcList[i % 3]
          }
          list.push(listItem)
        }
        return list
      },
      onSwiperChange(e : SwiperChangeEvent) {
        // console.error('SwiperChangeEvent',e.detail.current);
        this.current = e.detail.current;
      },
      onTransition(/*e : SwiperTransitionEvent*/) {
        // console.log('onTransition e.detail.dx', e.detail.dx);
      },
      back() {
        uni.navigateBack({
          success(result) {
            console.log('navigateBack success', result.errMsg)
          },
          fail(error) {
            console.log('navigateBack fail', error.errMsg)
          },
          complete(result) {
            console.log('navigateBack complete', result.errMsg)
          }
        })
195
      }
雪洛's avatar
雪洛 已提交
196 197
    }
  }
198 199 200
</script>

<style>
雪洛's avatar
雪洛 已提交
201 202
  .page {
    width: 750rpx;
203
    flex: 1;
雪洛's avatar
雪洛 已提交
204
  }
205

雪洛's avatar
雪洛 已提交
206 207 208 209 210 211 212 213
  .swiper,
  .swiper-item,
  .video-box,
  .video-cover {
    width: 750rpx;
    flex: 1;
    height: 100%;
  }
214

雪洛's avatar
雪洛 已提交
215 216 217
  .swiper-item {
    position: relative;
  }
218

雪洛's avatar
雪洛 已提交
219 220
  .video-box {
    width: 750rpx;
221 222
  }

雪洛's avatar
雪洛 已提交
223
  .video-cover {
224
    position: absolute;
雪洛's avatar
雪洛 已提交
225 226 227
    justify-content: center;
    align-items: center;
    align-content: center;
228 229
  }

雪洛's avatar
雪洛 已提交
230 231 232 233
  .play-btn {
    width: 80rpx;
    height: 80rpx;
  }
234

雪洛's avatar
雪洛 已提交
235 236 237 238 239
  .video-info {
    position: absolute;
    bottom: 0;
    padding: 15px;
  }
240

雪洛's avatar
雪洛 已提交
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
  .video-info-text {
    font-size: 14px;
    color: red;
    line-height: 20px;
  }

  .debug-info {
    position: fixed;
    top: 15px;
    width: 750rpx;
    background-color: rgba(255, 255, 255, 0.3);
  }

  .status-text {
    color: red;
    padding: 15px;
  }

  .nav-back {
    position: absolute;
    top: 20px;
    left: 8px;
    background-color: rgba(220, 220, 220, 0.8);
    border-radius: 100px;
    width: 28px;
    height: 28px;
    justify-content: center;
    align-items: center;
    z-index: 10;
  }

  .nav-back .back-img {
    width: 18px;
    height: 18px;
  }
</style>