通过webrtc+canvas+css实现简单的电脑滤镜照相结果

打印 上一主题 下一主题

主题 912|帖子 912|积分 2736

        这里我们用的是webrtc中的MediaDevices.getUserMedia()的欣赏器api进行的结果实现,MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的允许,媒体输入会产生一个MediaStream,里面包罗了哀求的媒体范例的轨道。此流可以包罗一个视频轨道(来自硬件大概虚拟视频源,比如相机、视频采集装备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其他轨道范例。
        它返回一个Promise对象,成功后会resolve回调一个MediaStream对象。若用户拒绝了使用权限,大概需要的媒体源不可用,promise会reject回调一个 PermissionDeniedError 大概 NotFoundError 。
代码:
HTML:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>webrtc实现拍照和滤镜</title>
  7.     <link rel="stylesheet" href="./index.css">
  8. </head>
  9. <body>
  10.     <div id="container" style="width: fit-content;height: fit-content;position: relative;">
  11.         <video id="video" src=""></video>
  12.         <div id="filter" class="filter"></div>
  13.     </div>
  14.     <select id="select">
  15.         <option value="">无滤镜</option>
  16.         <option value="style1">滤镜1</option>
  17.         <option value="style2">滤镜2</option>
  18.         <option value="style3">滤镜3</option>
  19.     </select>
  20.     <h3>截图展示</h3>
  21.     <button id="snap">截图</button>
  22. </body>
  23. <script src="./index.js"></script>
  24. </html>
复制代码
 js:
  1. //获取视频流
  2. const constraints = {
  3.     video: {
  4.         width: { min: 300, ideal: 600, max: 900 },
  5.         height: { min: 300, ideal: 600, max: 900 },
  6.         frameRate: { ideal: 60, max: 120 }, //帧率
  7.     }
  8. }
  9. navigator
  10.     .mediaDevices
  11.     .getUserMedia(constraints)
  12.     .then(function (stream) {
  13.         const video = document.querySelector('video')
  14.         video.srcObject = stream;
  15.         video.onloadedmetadata = function (e) {
  16.             video.play();
  17.         }
  18.     })
  19.     .catch(function (err) {
  20.         console.log("启动失败", err)
  21.     })
  22. //设置视频流滤镜
  23. const video = document.querySelector('.filter')
  24. const selectVal = document.querySelector('#select')
  25. selectVal.addEventListener('change', () => {
  26.     video.className = 'filter' // 清空之前的类名
  27.     if (selectVal.value) {
  28.         video.classList.add(selectVal.value) // 添加新的类名
  29.     }
  30. })
  31. const snapButton = document.querySelector('#snap');
  32. snapButton.addEventListener('click', () => {
  33.     const canvas = document.createElement('canvas')
  34.     const video = document.getElementById('video');
  35.     const filterDiv = document.getElementById('filter');
  36.     console.log(video,filterDiv)
  37.     const ctx = canvas.getContext('2d');
  38.     // 设置 Canvas 的宽高与容器相同
  39.     const container = document.getElementById('container');
  40.     canvas.width = container.offsetWidth;
  41.     canvas.height = container.offsetHeight;
  42.     // 绘制视频的当前帧
  43.     ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
  44.     // 绘制滤镜层
  45.     ctx.fillStyle = window.getComputedStyle(filterDiv).backgroundColor;
  46.     ctx.fillRect(0, 0, canvas.width, canvas.height);
  47.     // 导出图像并显示
  48.     const imgData = canvas.toDataURL('image/png');
  49.     const img = document.createElement('img');
  50.     img.src = imgData;
  51.     document.body.appendChild(img);
  52. })
复制代码
这里留意: 报错为OverconstrainedError时,看一下自己分辨率是否过大
css:
  1. :root {
  2.     --back-style: unset;
  3. }
  4. .filter {
  5.     content: '';
  6.     position: absolute;
  7.     top: 0;
  8.     left: 0;
  9.     width: 100%;
  10.     height: 100%;
  11.     background: var(--back-style);
  12.     z-index: 2;
  13.     pointer-events: none;
  14. }
  15. .style1 {
  16.     --back-style: rgba(0, 0, 0, 0.2);
  17. }
  18. .style2 {
  19.     --back-style: rgba(255, 255, 255, 0.2);
  20. }
  21. .style3 {
  22.     --back-style: rgba(0, 0, 255, 0.2);
  23. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张国伟

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表