1.视频播放组件
<template>
<div
class="m-video"
:class="{ 'u-video-hover': !hidden, 'u-video-play': play }"
:style="`width: ${veoWidth}; height: ${veoHeight};`"
>
<video
ref="veoRef"
class="u-video"
:style="`object-fit: ${zoom};`"
:src="src"
:poster="veoPoster"
:autoplay="autoplay"
:controls="!originPlay && controls"
:loop="loop"
:muted="autoplay || muted"
:preload="preload"
crossorigin="anonymous"
@loadeddata="poster ? () => false : getPoster()"
@pause="showPlay ? onPause() : () => false"
@playing="showPlay ? onPlaying() : () => false"
@click.prevent="onPlay"
v-bind="$attrs"
>
您的浏览器不支持video标签。
</video>
<img
v-show="play"
src="@/assets/applyForOil/icon_close_youweweima.png"
alt=""
class="close-btn"
@click="closeHandle()"
/>
<svg
v-show="originPlay"
class="u-play"
:class="{ hidden: hidden }"
:style="`width: ${playWidth}px; height: ${playWidth}px;`"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
d="M4.75 6.75C4.75 5.64543 5.64543 4.75 6.75 4.75H17.25C18.3546 4.75 19.25 5.64543 19.25 6.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H6.75C5.64543 19.25 4.75 18.3546 4.75 17.25V6.75Z"
></path>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
d="M15.25 12L9.75 8.75V15.25L15.25 12Z"
></path>
</svg>
</div>
</template>
<script>
export default {
name: "Video",
props: {
src: {
type: String,
required: true,
default: "",
},
poster: {
type: String,
default: "",
},
second: {
type: Number,
default: 0.5,
},
width: {
type: [String, Number],
default: 100,
},
height: {
type: [String, Number],
default: 100,
},
autoplay: {
type: Boolean,
default: false,
},
controls: {
type: Boolean,
default: true,
},
loop: {
type: Boolean,
default: false,
},
muted: {
type: Boolean,
default: false,
},
preload: {
type: String,
default: "metadata",
},
showPlay: {
type: Boolean,
default: true,
},
playWidth: {
type: Number,
default: 36,
},
zoom: {
type: String,
default: "contain",
},
},
data() {
return {
veoPoster: this.poster,
originPlay: true,
play: false,
hidden: false,
};
},
computed: {
veoWidth() {
if (typeof this.width === "number") {
return this.width + "px";
}
return this.width;
},
veoHeight() {
if (typeof this.height === "number") {
return this.height + "px";
}
return this.height;
},
},
mounted() {
},
methods: {
getPoster() {
this.$refs.veoRef.currentTime = this.second;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = this.$refs.veoRef.videoWidth;
canvas.height = this.$refs.veoRef.videoHeight;
ctx.drawImage(this.$refs.veoRef, 0, 0, canvas.width, canvas.height);
this.veoPoster = canvas.toDataURL("image/png");
},
onPlay() {
this.play = true;
if (this.originPlay) {
this.$refs.veoRef.currentTime = 0;
this.$refs.veoRef.play();
}
if (this.autoplay) {
this.$refs.veoRef.pause();
} else {
this.hidden = true;
this.$refs.veoRef.play();
}
},
closeHandle() {
this.play = false;
},
onPause() {
this.hidden = false;
},
onPlaying() {
this.hidden = true;
},
},
};
</script>
<style lang="scss" scoped>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.close-btn {
position: absolute;
right: 20px;
width: 30px;
height: 30px;
top: 30px;
z-index: 9999;
}
.u-video-play {
position: fixed !important;
top: 0;
left: 0;
width: 100vw !important;
height: 100vh !important;
z-index: 999;
}
.m-video {
display: inline-block;
position: relative;
background: #000;
cursor: pointer;
.u-video {
display: inline-block;
width: 100%;
height: 100%;
vertical-align: bottom;
}
.u-play {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
fill: none;
color: #fff;
pointer-events: none;
opacity: 0.7;
transition: opacity 0.3s;
path {
stroke: #fff;
}
}
.hidden {
opacity: 0;
}
}
.u-video-hover {
&:hover {
.u-play {
opacity: 0.9;
}
}
}
</style>
2.组件调用
<van-field
class="uploader"
name="uploader"
label="举证照片/视频"
required
>
<template #input>
<span class="tooltip">(至上少上传3张照片或3段视频)</span>
<ul class="uploader-warp">
<li
class="uploader-item"
v-for="(item, index) in uploader"
:key="index"
>
<van-image
v-if="item.type == 'pic'"
:src="item.url"
class="van-image"
>
<template v-slot:loading>
<van-loading type="spinner" size="20" />
</template>
</van-image>
<Video v-else :src="item.url" :second="3" />
<img
src="@/assets/applyForOil/icon_close_youweweima.png"
alt=""
class="deleet"
@click="deleteHandle(item, index)"
/>
</li>
<li class="uploader-item" v-if="showIs" @click="handleUpload">
<div class="uploader-box">
<div class="uploader-pic">
<img src="@/assets/applyForOil/icon_add.png" alt="" />
<p>上传</p>
</div>
</div>
</li>
</ul>
</template>
</van-field>
============================
handleUpload() {
lightAppJssdk.media.chooseVideoAndPic({
arg: "",
success: (data) => {
if (data.result == "true") {
if (data.videoPath) {
this.uploader.push({
url: data.videoPath,
type: "video",
});
} else {
this.uploader.push({
url: data.picPath[0],
type: "pic",
});
}
if (this.uploader.length >= 5) {
this.showIs = false;
}
}
},
fail: (data) => {
console.log("fail", data);
this.$toast({
message: "相机/相册调用失败",
icon: "close",
});
},
});
},