This commit is contained in:
kk
2026-07-08 18:00:33 +08:00
commit e66b4a3680
312 changed files with 54718 additions and 0 deletions
+140
View File
@@ -0,0 +1,140 @@
<template>
<div :style="styleName" class="basic-video">
<div class="basic-video__border">
<span :style="borderStyleName"></span>
<span :style="borderStyleName"></span>
<span :style="borderStyleName"></span>
<span :style="borderStyleName"></span>
</div>
<img :style="imgStyleName" class="basic-video__img" :src="background" />
<video class="basic-video__main" ref="main" autoplay muted></video>
</div>
</template>
<script>
import RecordVideo from './plugin';
export default {
name: 'basic-video',
props: {
background: {
type: String,
},
width: {
type: [String, Number],
default: 500,
},
},
computed: {
styleName() {
return {
width: `${this.width}px`,
};
},
imgStyleName() {
return {
width: `${this.width / 2}px`,
};
},
borderStyleName() {
return {
width: `${this.width / 15}px`,
height: `${this.width / 15}px`,
borderWidth: `${5}px`,
};
},
},
data() {
return {
videoObj: null,
};
},
mounted() {
this.init();
},
methods: {
init() {
this.videoObj = new RecordVideo(this.$refs.main);
const videoPromise = this.videoObj.init();
videoPromise.then(() => {
this.videoObj.mediaRecorder.addEventListener('stop', this.getData, false);
});
},
startRecord() {
this.videoObj.startRecord();
},
stopRecord() {
this.videoObj.stopRecord();
},
getData() {
const blob = new Blob(this.videoObj.chunks, {
type: 'video/mp4',
});
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.addEventListener('loadend', () => {
var video_base64 = reader.result;
this.$emit('data-change', video_base64);
});
},
},
};
</script>
<style lang="scss" scoped>
.basic-video {
margin: 0 auto;
position: relative;
overflow: hidden;
&__border {
span {
position: absolute;
width: 30px;
height: 30px;
border-width: 4px;
color: #0073eb;
border-style: solid;
&:nth-child(1) {
left: 15px;
top: 15px;
border-right: 0;
border-bottom: 0;
}
&:nth-child(2) {
right: 15px;
top: 15px;
border-left: 0;
border-bottom: 0;
}
&:nth-child(3) {
bottom: 15px;
left: 15px;
border-right: 0;
border-top: 0;
}
&:nth-child(4) {
bottom: 15px;
right: 15px;
border-left: 0;
border-top: 0;
}
}
}
&__img {
width: 100px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
&__main {
width: 100%;
}
}
</style>
+88
View File
@@ -0,0 +1,88 @@
export default class RecordVideo {
/**
* 构造函数
*
* @param {Object} videoObj 视频对象
*/
constructor(videoObj) {
this.video = videoObj;
this.mediaRecorder = null;
this.chunks = [];
}
/**
* 初始化
*
* @return {Object} promise
*/
init() {
// 返回Promise对象
// resolve 正常处理
// reject 处理异常情况
return new Promise((resovle, reject) => {
navigator.mediaDevices
.getUserMedia({
audio: true,
video: true,
// video: {
// width: this.videoWidth,
// height: this.videoHeight
// }
})
// 返回一个媒体内容的流
.then(stream => {
// 检测是否支持 srcObject,该属性在新的浏览器支持
if ('srcObject' in this.video) {
this.video.srcObject = stream;
} else {
// 兼容旧的浏览器
this.video.src = window.URL.createObjectURL(stream);
}
// 当视频的元数据已经加载时触发
this.video.addEventListener('loadmetadata', () => {
this.video.play();
});
this.mediaRecorder = new MediaRecorder(stream);
this.mediaRecorder.addEventListener('dataavailable', e => {
this.chunks.push(e.data);
});
resovle();
})
// 异常抓取,包括用于禁用麦克风、摄像头
.catch(error => {
reject(error);
});
});
}
/**
* 视频开始录制
*/
startRecord() {
if (this.mediaRecorder.state === 'inactive') {
this.mediaRecorder.start();
}
}
/**
* 视频结束录制
*/
stopRecord() {
if (this.mediaRecorder.state === 'recording') {
this.mediaRecorder.stop();
}
}
/**
* 检测当前浏览器对否支持
*
* @return {boolean} 当前浏览器是否支持
*/
isSupport() {
const flag = navigator.mediaDevices && navigator.mediaDevices.getUserMedia;
if (flag) {
return true;
}
}
}