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

預覽

簡易的預覽鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章