123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- <template>
- <view class="page">
- <view ref="back" @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" :id="'video-'+i"
- @loadstart="onLoadstart(i)" :src="item.src" :poster="item.poster_src" :autoplay="false"
- :show-progress="false" :show-fullscreen-btn="false" :show-play-btn="false"
- :show-center-play-btn="false" :loop="true" @play="onPlay(i)" @pause="onPause(i)" http-cache="true"></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="showDebugInfo">
- <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="showDebugInfo">
- <text class="status-text">debug-info 播放状态:</text>
- <text class="status-text" v-for="(value,index) in state">第{{index+1}}个:{{ value }}</text>
- </view>
- </view>
- </template>
- <script>
- type ListItem = { _id : string, content : string, src : string, poster_src : string }
- let page : number = 0,
- currentPageIsShow : boolean = true;
- import { state, setNetless } from '@/store/index.uts'
- export default {
- components: {},
- data() {
- return {
- $videoContextMap: new Map<string, VideoContext>(),
- list: [] as ListItem[],
- visibleList: [] as ListItem[],// 提高性能 可见的只有3个
- current: 0 as number,
- index: 0,
- state: ["pause", "unPlay", "unPlay"] as string[],
- showDebugInfo: false as boolean
- }
- },
- created() {
- // #ifdef APP-HARMONY
- uni.getNetworkType({
- success: (res) => {
- setNetless(res.networkType === 'none')
- // #endif
- this.list = this.getData()
- this.visibleList = this.list.slice(0, 3)
- // #ifdef APP-HARMONY
- }
- })
- // #endif
- },
- 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)
- }
- 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() {
- // #ifdef APP || MP
- // 非web端,一启动完成,就播放第一个。因为 web端浏览器限制不支持自动播放
- this.doPlay(0);
- //App端适配不同状态栏高度
- let backElement = this.$refs['back'] as UniElement;
- backElement.style.setProperty('top', uni.getWindowInfo().statusBarHeight+'px');
- // #endif
- },
- onShow() {
- currentPageIsShow = true
- },
- onHide() {
- currentPageIsShow = false
- console.log('pages-onHide');
- this.doPause(this.current)
- },
- 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.get('video-' + index)
- if (videoContext == null) {
- videoContext = uni.createVideoContext('video-' + index, this) as VideoContext
- videoContextMap.set('video-' + index, videoContext)
- }
- return videoContext
- },
- doPlay(index : number) {
- console.log("doPlay video" + index);
- this.getVideoContext(index).play()
- },
- 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);
- }
- },
- getData() : ListItem[] {
- let videoUrlList = state.netless
- ? [
- '/static/test-video/10second-demo.mp4',
- '/static/test-video/10second-demo.mp4',
- '/static/test-video/10second-demo.mp4'
- ]
- : [
- 'https://web-ext-storage.dcloud.net.cn/uni-app-x/video/uts-5-16.mp4',
- 'https://web-ext-storage.dcloud.net.cn/uni-app-x/video/uni-ai-5-16.mp4',
- 'https://web-ext-storage.dcloud.net.cn/uni-app-x/video/uni-verify-5-16.mp4'
- ] as string[]
- let posterSrcList = state.netless
- ? [
- '/static/shuijiao.jpg',
- '/static/logo.jpg',
- '/static/shuijiao.jpg'
- ]
- : [
- 'https://web-ext-storage.dcloud.net.cn/uni-app-x/dark-uni-uts-01.png',
- 'https://web-ext-storage.dcloud.net.cn/uni-app-x/dark-uni-ai-01.png',
- 'https://web-ext-storage.dcloud.net.cn/uni-app-x/dark-uni-verify-01.jpg'
- ] as string[]
- 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)
- }
- })
- }
- }
- }
- </script>
- <style>
- .page {
- flex: 1;
- }
- .swiper,
- .swiper-item,
- .video-box,
- .video-cover {
- width: 100%;
- height: 100%;
- }
- .swiper-item {
- position: relative;
- }
- .video-box {
- width: 100%;
- }
- .video-cover {
- position: absolute;
- justify-content: center;
- align-items: center;
- align-content: center;
- }
- .play-btn {
- width: 40px;
- height: 40px;
- }
- .video-info {
- position: absolute;
- bottom: 0;
- padding: 15px;
- }
- .video-info-text {
- font-size: 14px;
- color: red;
- line-height: 20px;
- }
- .debug-info {
- position: fixed;
- top: 15px;
- width: 100%;
- background-color: rgba(255, 255, 255, 0.3);
- }
- .status-text {
- color: red;
- padding: 15px;
- }
- .nav-back {
- position: absolute;
- /* #ifdef APP */
- top: 35px;
- /* #endif */
- background-color: rgba(220, 220, 220, 0.8);
- border-radius: 100px;
- margin: 6px;
- width: 32px;
- height: 32px;
- justify-content: center;
- align-items: center;
- z-index: 10;
- }
- .nav-back .back-img {
- width: 18px;
- height: 18px;
- }
- </style>
|