init
This commit is contained in:
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user