一、概述
各个银行app都有人脸识别功能,就是一个圆形的录像界面。这一章节主要学习如何使用vedio标签,以及将录像形状调整为圆形。 实现效果如下:
二、知识点
2.1 vedio标签的使用
其核心代码如下,在开始录制视频的时候,通过MediaRecorder收集视频的字节,并在录制结束的时候转换为Blob对象,再通过FileReader转换为base64格式的数据。
startRecording() {
console.log('开始录制视频');
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
this.video.srcObject = stream;
this.video.play();
this.mediaRecorder = new MediaRecorder(stream);
this.recordedChunks = [];
this.isRecording = true;
this.mediaRecorder.ondataavailable = (event) => {
if (event.data && event.data.size > 0) {
this.recordedChunks.push(event.data);
}
};
this.mediaRecorder.start(100); // 每 100 毫秒收集一次数据
});
}
stopRecording() {
// 在停止录制视频时,首先打印日志信息
console.log('停止录制视频');
// 检查是否存在mediaRecorder实例
if (this.mediaRecorder) {
// 停止录制
this.mediaRecorder.stop();
// 重置mediaRecorder实例
this.mediaRecorder = null;
this.isRecording = false;
// 将录制的Chunk数据块组合成一个Blob对象
const blob = new Blob(this.recordedChunks, { type: 'video/webm' });
// 将Blob对象转换为Base64字符串
const fileReader = new FileReader();
fileReader.onload = (e) => {
this.recordedBase64Data = e.target.result;
};
fileReader.readAsDataURL(blob);
// 将Blob对象转换为URL,便于在网页中使用
this.recordedBlobUrl = URL.createObjectURL(blob);
// 重置录制的Chunk数据块数组
this.recordedChunks = [];
}
}
2.2 vedio的样式
圆形的录制界面,是通过样式来调整的,如下:
/**
* .video-container 类的样式定义
* 该类用于创建一个相对定位的容器,容器为一个圆形,用于展示视频
* 容器的宽高为200px,有圆角和隐藏溢出内容的属性,顶部有20px的外边距
*/
.video-container {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
margin-top: 20px;
}
/**
* .video-container 类下的 video 元素的样式定义
* 该类用于绝对定位容器中的视频元素,并且使视频元素的中心点与容器的中心点对齐
* 视频元素的宽高设置为100%,确保视频能够填满容器,并且保持宽高比正确缩放
*/
.video-container video {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
object-fit: cover;
}
三、实现
完整实现如下:
<template>
<div class="recording-container">
<div class="video-container recording">
<video ref="video" width="200" height="200" autoplay muted playsinline></video>
</div>
<button @click="startRecording" class="custom-camera-button">开始录像</button>
<button @click="stopRecording" class="custom-camera-button">停止录像</button>
<div v-if="recordedBlobUrl" class="video-container">
<h2>已录制的视频</h2>
<video :src="recordedBlobUrl" controls width="640" height="480"></video>
</div>
</div>
</template>
<script>
export default {
data() {
return {
video: null,
mediaRecorder: null,
recordedChunks: [],
recordedBlobUrl: null,
recordedBase64Data: null,
isRecording: false
};
},
methods: {
/**
* 开始录像
*
* 此方法用于创建 MediaRecorder 对象并开始录制视频
*/
startRecording() {
console.log('开始录制视频');
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
this.video.srcObject = stream;
this.video.play();
this.mediaRecorder = new MediaRecorder(stream);
this.recordedChunks = [];
this.isRecording = true;
this.mediaRecorder.ondataavailable = (event) => {
if (event.data && event.data.size > 0) {
this.recordedChunks.push(event.data);
}
};
this.mediaRecorder.start(100); // 每 100 毫秒收集一次数据
});
},
/**
* 停止录像
*
* 此方法用于停止录制视频并将录制的数据转换为 Blob URL
*/
stopRecording() {
// 在停止录制视频时,首先打印日志信息
console.log('停止录制视频');
// 检查是否存在mediaRecorder实例
if (this.mediaRecorder) {
// 停止录制
this.mediaRecorder.stop();
// 重置mediaRecorder实例
this.mediaRecorder = null;
this.isRecording = false;
// 将录制的Chunk数据块组合成一个Blob对象
const blob = new Blob(this.recordedChunks, { type: 'video/webm' });
// 将Blob对象转换为Base64字符串
const fileReader = new FileReader();
fileReader.onload = (e) => {
this.recordedBase64Data = e.target.result;
};
fileReader.readAsDataURL(blob);
// 将Blob对象转换为URL,便于在网页中使用
this.recordedBlobUrl = URL.createObjectURL(blob);
// 重置录制的Chunk数据块数组
this.recordedChunks = [];
}
}
},
mounted() {
this.video = this.$refs.video;
}
};
</script>
<style scoped>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
/* 自定义相机控制按钮 */
.custom-camera-button {
background-color: #1890ff;
/* 蓝色背景 */
color: white;
/* 白色文字 */
border: none;
padding: 10px 20px;
cursor: pointer;
font-size: 16px;
border-radius: 4px;
outline: none;
margin: 10px;
}
.custom-camera-button:hover {
background-color: #1377db;
/* 鼠标悬停时更深的蓝色 */
}
.recording-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 20px;
}
/**
* .video-container 类的样式定义
* 该类用于创建一个相对定位的容器,容器为一个圆形,用于展示视频
* 容器的宽高为200px,有圆角和隐藏溢出内容的属性,顶部有20px的外边距
*/
.video-container {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
margin-top: 20px;
}
/**
* .video-container 类下的 video 元素的样式定义
* 该类用于绝对定位容器中的视频元素,并且使视频元素的中心点与容器的中心点对齐
* 视频元素的宽高设置为100%,确保视频能够填满容器,并且保持宽高比正确缩放
*/
.video-container video {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
四、总结
工具用得好,学习也就快,借助AI做的,自己主要负责提问。