如果要实现一个类似人脸识别的界面,要求使用 canvas 进行绘制,中间镂空透明区域,背景是白色的画布。
技术方案:
- 首先,使用 canvas 绘制一个白色画布
- 其次,使用 context.globalCompositeOperation 合成属性进行多图层处理
UI 绘制
<section><video id="video-preview" width="0%" height="0%" autoPlay /><div><canvas id="video-canvas" width="300" height="300" /></div><button id="start-recording">start</button><button id="stop-recording" disabled>stop</button>
</section>
逻辑实现(纯js实现)
// 获取 DOM 元素
const video: any = document.getElementById('video-preview');const canvas: any = document.getElementById('video-canvas');
const ctx = canvas.getContext('2d');// 设定遮罩区域的尺寸
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const outerRadius = Math.min(centerX, centerY) * 0.9;// 绘制视频帧
function drawFrame() {// 绘制 Video 流ctx.drawImage(video, 0, 0, canvas.width, canvas.height);ctx.beginPath();ctx.arc(centerX, centerY, outerRadius, 0, 2 * Math.PI);ctx.globalCompositeOperation = 'destination-in'; // 使用复合操作使颜色变为透明ctx.fill();// 恢复默认的混合模式ctx.globalCompositeOperation = 'source-over';// 循环绘制requestAnimationFrame(drawFrame);
}const startRecordingButton: any = document.getElementById('start-recording');
const stopRecordingButton: any = document.getElementById('stop-recording');// 录制状态标志
let isRecording: any = false;
let recordedBlobs: any = [];
let mediaRecorder: any = null;
let stream: any = null;// 请求访问媒体设备
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then((_stream) => {stream = _stream;video.srcObject = stream; // 设置视频源}).catch((err) => console.error('Error:', err));// 等待视频流就绪
video.addEventListener('canplay', () => {drawFrame();
});
// 开始录制按钮点击事件处理函数
startRecordingButton.addEventListener('click', () => {if (!isRecording) {isRecording = true;startRecordingButton.disabled = true;stopRecordingButton.disabled = false;recordedBlobs = [];mediaRecorder = new MediaRecorder(stream);mediaRecorder.ondataavailable = (event) => {if (event.data && event.data.size > 0) {recordedBlobs.push(event.data);}};mediaRecorder.onstop = () => {// 录制结束后,合并 Blobconst blob = new Blob(recordedBlobs, { type: 'video/mp4' });const url = URL.createObjectURL(blob);const a = document.createElement('a');document.body.appendChild(a);a.style.display = 'none';a.href = url;a.download = 'recorded-video.mp4';a.click();window.URL.revokeObjectURL(url);};mediaRecorder.start();}
});// 停止录制按钮点击事件处理函数
stopRecordingButton.addEventListener('click', () => {if (isRecording) {mediaRecorder.stop();isRecording = false;startRecordingButton.disabled = false;stopRecordingButton.disabled = true;}
});
在线查看
点击查看