WebRTC從攝像頭獲取圖片傳入canvas
這是我參與11月更文挑戰的第6天,活動詳情檢視:2021最後一次更文挑戰
前面我們已經能夠利用WebRTC的功能,通過瀏覽器開啟攝像頭,並把預覽的影象顯示在video元素中。 接下來我們嘗試從影片中擷取某一幀,顯示在介面上。
html
先準備一下介面,擺上控制元件。下面是關鍵部分的程式碼。 ```html
```
- video 用來預覽影片
- 3個button,分別拿來開啟攝像頭,擷取圖片和清除記錄
- canvas 用來顯示擷取的圖片
- 下面的div是拿來存放多個擷取圖片記錄的。給它指定了grid,顯示多個圖片時候比較好看一些
照例,需要引入adapter-latest.js
```html
```
js
準備實現功能。
開啟攝像頭並預覽
和之前的開啟攝像頭類似,還是要用到getUserMedia
方法。拿到影片流後交給video去播放。
```js
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,先預定一個尺寸(不預定也行)。 ```js 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,把它們像相簿一樣展示出來。
```js 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
)裡的子項。用一個迴圈獲取並移除子項。
js
var child = list.lastElementChild;
while (child) {
list.removeChild(child);
child = list.lastElementChild;
}
小結
開啟攝像頭,顯示影片。把影片繪製到canvas上。建立多個canvas,做成歷史記錄的效果。 主要利用的還是canvas的繪製方法。繪製的時候注意傳入的引數,能夠指定繪製的邊界。 也就是說只繪製影片大小中的一部分也是可行的。
示例中用到的關鍵方法
getUserMedia
getContext
drawImage
createElement
簡易的預覽連結