123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- <template>
- <view class="video-box" v-loading="loading">
- <video
- v-if="videoUrl"
- class="video-box-body"
- id="myVideo"
- @timeupdate="timeUpdate"
- :src="videoUrl"
- controls
- :initial-time="initial_time"
- object-fit="fill"
- play-btn-position="center"
- @ended="ended"
- @tap="videoClick"
- @loadedmetadata="loadedmetadata"
- >
- <cover-view class="video-control">
- <cover-view class="multi rate" @tap.stop="showSwitchRate">x {{ currentRate }}</cover-view>
- </cover-view>
- <cover-view class="multi-list rate" :class="{ active: rateShow }">
- <cover-view
- v-for="(item, index) in rateList"
- :key="index"
- class="multi-item rate"
- :data-rate="item"
- @tap="switchRate"
- :class="{ active: item == currentRate }"
- >
- {{ item }}
- </cover-view>
- </cover-view>
- </video>
- <view class="video-box-body" v-else>
- <u-empty text="视频地址为空" mode="page"></u-empty>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'VideoBox',
- props: {
- rateList: {
- type: Array,
- default: () => ['0.5', '1.0', '1.5', '2.0']
- },
- videoUrl: {
- type: String,
- default: ''
- }
- },
- data() {
- return {
- // 加载层
- loading: false,
- // 视频创建dom
- videoContext: uni.createVideoContext('myVideo', this),
- // 视频实时时间
- initial_time: 0,
- // 视频已经播放时间
- playedTime: 0,
- // 倍速浮层
- rateShow: false,
- // 默认倍速
- currentRate: 1.0,
- // 视频实际时间
- video_real_time: 0,
- // 视频总时长
- duration: 0,
- // 当前视频选中播放
- currentDuration: 0,
- // 视频信息
- videoInfo: {},
- // 选中课程下标
- videoIndex: 0
- };
- },
- methods: {
- /**
- * 加载视频
- * @date 2022-10-19
- * @returns {any}
- */
- loadVideo(data) {
- this.loading = true;
- this.videoInfo = data;
- this.initial_time = Number(data.currentDuration);
- this.video_real_time = Number(data.playDuration);
- this.playedTime = Number(data.playDuration);
- },
- /**
- * 记录时间
- * @date 2022-10-19
- * @param { Number } index
- * @returns {any}
- */
- recordDuration(index, refresh) {
- this.videoIndex = index;
- let playDuration = this.video_real_time;
- if (this.videoInfo.playDuration > this.video_real_time) {
- this.currentDuration = this.video_real_time;
- playDuration = this.videoInfo.playDuration;
- } else {
- this.currentDuration = this.video_real_time;
- }
- this.$emit('recordDuration', { playDuration, duration: this.duration, currentDuration: this.currentDuration }, index, refresh);
- },
- /**
- * 获取视频总时长
- * @param {Object} data
- */
- loadedmetadata(data) {
- this.duration = data.detail.duration;
- this.loading = false;
- },
- /**
- * 显示倍速浮层
- * @date 2022-10-19
- * @returns {any}
- */
- showSwitchRate() {
- this.rateShow = true;
- },
- /**
- * 切换倍速
- * @param {Object} e
- */
- switchRate(e) {
- let rate = Number(e.currentTarget.dataset.rate);
- this.currentRate = rate;
- this.rateShow = false;
- this.videoContext.playbackRate(rate);
- },
- /**
- * 视频点击
- * @param {Object} e
- */
- videoClick(e) {
- this.rateShow = false;
- },
- /**
- * 视频停止
- * @date 2022-10-19
- * @param {any} e
- * @returns {any}
- */
- pause(e) {
- console.log(e);
- },
- /**
- * 控制视频不能快进
- * @param {Object} e
- */
- timeUpdate(e) {
- //播放的总时长
- let duration = e.detail.duration;
- //实时播放进度 秒数
- let jumpTime = parseInt(e.detail.currentTime);
- //当前视频进度
- if (jumpTime - this.playedTime > 3) {
- // 差别过大,调用seek方法跳转到实际观看时间
- this.videoContext.seek(this.playedTime);
- wx.showToast({
- title: '未完整看完该视频,不能快进',
- icon: 'none',
- duration: 2000
- });
- } else {
- this.video_real_time = parseInt(e.detail.currentTime);
- this.currentDuration = e.detail.currentTime
- if (this.video_real_time > this.playedTime) {
- this.playedTime = this.video_real_time;
- }
- }
- },
- /**
- * 视频结束
- */
- ended() {
- // 用户把进度条拉到最后,但是实际观看时间不够,跳转回去会自动暂停。
- // 这里加个判断。
- this.$emit(
- 'recordDuration',
- { playDuration: this.playedTime, duration: this.duration, currentDuration: this.currentDuration },
- this.videoIndex,
- false
- );
- }
- }
- };
- </script>
- <style lang="scss" scoped>
- .video-box {
- &-body {
- width: 100%;
- height: 400rpx;
- .video-control {
- background-color: rgba(0, 0, 0, 0.1);
- height: 90rpx;
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- z-index: 997;
- }
- .video-wrap {
- position: relative;
- }
- .multi-list.full-screen.vertical {
- height: 100vh !important;
- padding: 8vh 0;
- }
- .multi-list.full-screen.horizontal {
- height: 100vw !important;
- padding: 8vw 0;
- }
- .multi {
- position: absolute;
- right: 30rpx;
- top: 50%;
- transform: translateY(-50%);
- z-index: 998;
- width: 100rpx;
- color: #fff;
- padding: 10rpx 0;
- text-align: center;
- transition: color ease 0.3s;
- }
- .multi.rate {
- right: 30rpx;
- }
- .multi-list {
- position: absolute;
- height: 100%;
- width: 0;
- background-color: rgba(0, 0, 0, 0.65);
- top: 0;
- right: 0;
- transition: width 0.3s ease;
- z-index: 999;
- box-sizing: border-box;
- padding: 20rpx 0;
- }
- .multi-list.rate {
- padding: 25rpx 0;
- }
- .multi-list.active {
- width: 200rpx;
- }
- .multi-item {
- text-align: center;
- color: #fff;
- line-height: 80rpx;
- transition: color ease 0.3s;
- }
- .multi-item.rate {
- line-height: 70rpx;
- }
- .multi-item:hover,
- .multi:hover {
- color: #00d8ff;
- }
- .multi-item.active {
- color: #00d8ff;
- }
- }
- }
- </style>
|