zoukankan      html  css  js  c++  java
  • WebRTC从摄像头获取图片传入canvas

    WebRTC从摄像头获取图片传入canvas

    前面我们已经能够利用WebRTC的功能,通过浏览器打开摄像头,并把预览的图像显示在video元素中。
    接下来我们尝试从视频中截取某一帧,显示在界面上。

    html

    先准备一下界面,摆上控件。下面是关键部分的代码。

    <video playsinline autoplay></video>
    <button id="showVideo">打开摄像头</button>
    <button id="takeSnapshot">截取</button>
    <button id="clearList">清除记录</button>
    <canvas id="mainCanvas"></canvas>
    <div id="list" style="display: grid; grid-template-columns: repeat(auto-fill, 100px);
        column-gap: 20px; row-gap: 20px;"></div>
    
    • video 用来预览视频
    • 3个button,分别拿来打开摄像头,截取图片和清除记录
    • canvas 用来显示截取的图片
    • 下面的div是拿来存放多个截取图片记录的。给它指定了grid,显示多个图片时候比较好看一些

    照例,需要引入adapter-latest.js

    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    

    js

    准备实现功能。

    打开摄像头并预览

    和之前的打开摄像头类似,还是要用到getUserMedia方法。拿到视频流后交给video去播放。

    const video = document.querySelector('video');
    const constraints = {
      audio: false,
      video: true
    };
    // ....
    
    function openCamera(e) {
      navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(onError);
    }
    
    function gotStream(stream) {
      window.stream = stream;
      video.srcObject = stream;
    }
    
    function onError(error) {
      console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
    }
    

    截取图片

    拿到界面中的canvas,先预定一个尺寸(不预定也行)。

    const mCanvas = window.canvas = document.querySelector('#mainCanvas');
    mCanvas.width = 480;
    mCanvas.height = 360;
    
    // 开始截取
      mCanvas.width = video.videoWidth;
      mCanvas.height = video.videoHeight;
      mCanvas.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height);
    

    发起截取后,使用getContext获取到CanvasRenderingContext2D对象。然后调用它的drawImage方法。
    把video中的视频帧绘制进去。

    除了绘制这一个canvas,我们可以在每次发起(点击按钮)的时候创建新的canvas,把它们像相册一样展示出来。

    const list = document.querySelector('#list'); // 拿来存放多个元素
    
      // 新增1张
      var divItem = document.createElement("div");
      divItem.style.display = "block";
      divItem.width = 100;
      divItem.height = divItem.width * video.videoHeight / video.videoWidth; // 计算一下比例
      divItem.style.width = divItem.width + "px";
      divItem.style.height = divItem.height + "px";
      console.log("div item size: ", divItem.width, divItem.height);
    
      var c1 = document.createElement("canvas");
      c1.width = divItem.width;
      c1.height = divItem.height;
      c1.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height, 0, 0, c1.width, c1.height);
    
      divItem.appendChild(c1);
      list.appendChild(divItem);
    

    子项的存放方式是div包裹canvas。先用document.createElement("div")创建divItem
    按照视频的宽高,计算调整divItem的大小,并设置style。

    document.createElement("canvas")创建c1,它的宽高设置为前面divItem的宽高。然后把图片绘制进去。
    drawImage时,前面传入的是视频(源)的范围,后面的4个参数是自己的绘制范围。
    这样一个子项就生成完毕了。添加到我们准备好的列表(div)中。

    清除记录

    清除div(list)里的子项。用一个循环获取并移除子项。

    var child = list.lastElementChild;
    while (child) {
        list.removeChild(child);
        child = list.lastElementChild;
    }
    

    小结

    打开摄像头,显示视频。把视频绘制到canvas上。创建多个canvas,做成历史记录的效果。
    主要利用的还是canvas的绘制方法。绘制的时候注意传入的参数,能够指定绘制的边界。
    也就是说只绘制视频大小中的一部分也是可行的。

    示例中用到的关键方法

    • getUserMedia
    • getContext
    • drawImage
    • createElement

    预览

    简易的预览链接

    一个软件工程师的记录
  • 相关阅读:
    使用可传输表空间向rac环境迁移数据
    跨平台表空间传输(linux 10g表空间跨平台迁移到window 11g
    RAC+ASM在单机上恢复的过程
    Oracle RMAN进行的一次有益测试
    ORA-00600 4194 错误
    oracle表分区详解
    数据库最大连接数
    web传参
    内置
    键盘事件
  • 原文地址:https://www.cnblogs.com/rustfisher/p/15601315.html
Copyright © 2011-2022 走看看