<image :disabled="false" :controls='false' :autoplay='false' :src="item+'?x-oss-process=video/snapshot,t_0,f_jpg'" mode=""></image>
<template>
<view class="content image" @tap="showView(filePath)">
<video-content :filePath="filePath"></video-content>
</view>
</template>
import VideoContent from './components/videoContent.vue';
export default {
components: {
VideoContent
},
methods: {
showView(filePath) {
uni.navigateTo({
url: `/page/communication/components/videoView?filePath=${filePath}`
})
}
}
}
<template>
<view class="videoContent">
<!-- 播放按钮 -->
<view class="video-cover">
<image class="play-button" src="/static/communication/pc-play.png"></image>
</view>
<!-- 逻辑层调用视图层方法,采用监听data中变量改变的方法 -->
<view id="canvas" class="canvas" :prop="newVal" :change:prop="canvas.create"></view>
<!-- 逻辑层生成的图片回显 -->
<image class="image" :src="demo" mode=""></image>
</view>
</template>
<!-- 逻辑层script-->
<script>
export default {
name: 'videoContent',
props: {
// 图片地址
filePath: {
type: String
}
},
data() {
return {
demo: '',
}
},
computed: {
newVal() {
return this.filePath
}
},
onLoad() {
},
methods: {
getDataURL(options) {
this.demo = options.dataURL
}
}
}
</script>
<!-- 视图层script module对应HTML代码中view的id-->
<script module="canvas" lang="renderjs">
export default {
methods: {
// 视图层创建base64图片
create(newValue, oldValue, ownerInstance){
// 第一次进入为空不操作
if(newValue == null){
return
}
let video = document.createElement('video')
video.setAttribute('crossOrigin', 'anonymous') // 处理跨域,H5需后台支持,请求的视频资源响应投标需有Access-Control-Allow-Origin
video.setAttribute('src', newValue)
video.setAttribute('width', 200)
video.setAttribute('height', 200)
video.setAttribute('preload', 'auto')
// uni.chooseVideo选择视频,当选用手机拍摄的视频时,地址是相对地址,如 _doc/uniapp_temp_1650594368317/camera/1650594390147.mp4
// 可播放,但是loadeddata一直不执行,会触发error事件,视频加载失败
// 应先转换成本地地址
video.addEventListener('loadeddata', function () {
console.log('视频第一帧加载完')
let canvas = document.createElement('canvas')
let width = video.width // canvas的尺寸和图片一样
let height = video.height
canvas.width = width
canvas.height = height
canvas.getContext('2d').drawImage(video, 0, 0, width, height) // 绘制canvas
const dataURL = canvas.toDataURL('image/jpeg') // 转换为base64
// 传递数据给逻辑层
ownerInstance.callMethod('getDataURL',{
dataURL: dataURL
})
console.log('getVideoPoster-dataURL', dataURL.slice(0, 16))
})
video.addEventListener('error', err => {
console.log('视频加载失败', err)
})
}
}
}
</script>
<style lang="scss" scoped>
.videoContent {
position: relative;
.video-cover {
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(1, 1, 1, .5);
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
.play-button {
width: 40rpx;
height: 40rpx;
background-size: 50%;
background-repeat: no-repeat;
background-position: 50% 50%;
cursor: pointer;
}
}
.image {
max-width: 160rpx;
max-height: 260rpx;
}
}
</style>
<template>
<transition name="slide-fade">
<view class="videoView">
<cover-image class="cover-video" src="/static/communication/download.png" @tap="download"></cover-image>
<video id="popupVideo" :src="videoUrl" autoplay :show-fullscreen-btn="false" :show-center-play-btn="false">
</video>
</view>
</transition>
</template>
<script>
import http from '@/api/request'
import { toast } from '../../../utils'
export default {
data() {
return {
videoUrl: ''
}
},
onLoad({ filePath }) {
this.videoUrl = http.config.fileUrl + filePath
},
methods: {
download() {
console.log('this.videoUrl', this.videoUrl)
uni.downloadFile({
url: this.videoUrl,
success: (res) => {
if (res.statusCode === 200) {
uni.saveVideoToPhotosAlbum({
filePath: res.tempFilePath,
success: function () {
toast("保存成功");
},
fail: function () {
tToast("保存失败,请稍后重试");
}
});
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
.videoView {
video {
margin-top: 72rpx;
height: calc(100% - 72rpx);
width: 100%;
}
.close {
padding: 12rpx;
position: absolute;
top: 0;
right: 0;
image {
width: 48rpx;
height: 48rpx;
}
}
.cover-video {
display: block;
position: fixed;
right: 15rpx;
bottom: 15rpx;
width: 70rpx;
height: 70rpx;
z-index: 999;
}
}
</style>