通过webrtc+canvas+css实现简单的电脑滤镜拍照效果
这里我们用的是webrtc中的MediaDevices.getUserMedia()的浏览器api进行的效果实现,MediaDevices.getUserMedia()
会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其他轨道类型。
它返回一个Promise对象,成功后会resolve
回调一个MediaStream对象。若用户拒绝了使用权限,或者需要的媒体源不可用,promise
会reject
回调一个 PermissionDeniedError
或者 NotFoundError
。
代码:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>webrtc实现拍照和滤镜</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div id="container" style="width: fit-content;height: fit-content;position: relative;">
<video id="video" src=""></video>
<div id="filter" class="filter"></div>
</div>
<select id="select">
<option value="">无滤镜</option>
<option value="style1">滤镜1</option>
<option value="style2">滤镜2</option>
<option value="style3">滤镜3</option>
</select>
<h3>截图展示</h3>
<button id="snap">截图</button>
</body>
<script src="./index.js"></script>
</html>
js:
//获取视频流
const constraints = {
video: {
width: { min: 300, ideal: 600, max: 900 },
height: { min: 300, ideal: 600, max: 900 },
frameRate: { ideal: 60, max: 120 }, //帧率
}
}
navigator
.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
const video = document.querySelector('video')
video.srcObject = stream;
video.onloadedmetadata = function (e) {
video.play();
}
})
.catch(function (err) {
console.log("启动失败", err)
})
//设置视频流滤镜
const video = document.querySelector('.filter')
const selectVal = document.querySelector('#select')
selectVal.addEventListener('change', () => {
video.className = 'filter' // 清空之前的类名
if (selectVal.value) {
video.classList.add(selectVal.value) // 添加新的类名
}
})
const snapButton = document.querySelector('#snap');
snapButton.addEventListener('click', () => {
const canvas = document.createElement('canvas')
const video = document.getElementById('video');
const filterDiv = document.getElementById('filter');
console.log(video,filterDiv)
const ctx = canvas.getContext('2d');
// 设置 Canvas 的宽高与容器相同
const container = document.getElementById('container');
canvas.width = container.offsetWidth;
canvas.height = container.offsetHeight;
// 绘制视频的当前帧
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
// 绘制滤镜层
ctx.fillStyle = window.getComputedStyle(filterDiv).backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 导出图像并显示
const imgData = canvas.toDataURL('image/png');
const img = document.createElement('img');
img.src = imgData;
document.body.appendChild(img);
})
这里注意: 报错为OverconstrainedError时,看一下自己分辨率是否过大
css:
:root {
--back-style: unset;
}
.filter {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--back-style);
z-index: 2;
pointer-events: none;
}
.style1 {
--back-style: rgba(0, 0, 0, 0.2);
}
.style2 {
--back-style: rgba(255, 255, 255, 0.2);
}
.style3 {
--back-style: rgba(0, 0, 255, 0.2);
}