目標
我們先來觀察一下html吧
<div class="photobooth">
<div class="controls">
<button onClick="takePhoto()">Take Photo</button>
</div>
<canvas class="photo"></canvas>
<video class="player"></video>
<div class="strip"></div>
</div>
<audio class="snap" src="http://wesbos.com/demos/photobooth/snap.mp3" hidden></audio>
首先我們有一個video.player,可以用來播放攝像頭拍到的影片
接著我們會將擷取到的影片畫到canvas.photo上
const video = document.querySelector('.player');
function getVideo() {
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
.then(mediaStream => {
try {
video.srcObject = mediaStream;
} catch (err) {
video.src = window.URL.createObjectURL(mediaStream);
}
video.play();
});
};
getVideo();
我們要如何讀取攝像頭的影片呢?
可以使用navigator.mediaDevices來麥克風、攝影機或共享螢幕的連結
接著使用.getUserMedia()來取得許可.getUserMedia(constraints)的constraints參數有2個video和audio用來說明請求media的類型
必須至少一個可以被指定,寫法是
{video: boolean, audio: boolean}
我們這邊給video屬性值設定true而audio屬性值設定false
表示我們只要得到攝像頭的視訊,不需要麥克風的音訊getUserMedia()會讓我們得到一個Promise物件
再用.then來得到MediaStream這個物件
原本的寫法是
video.src = window.URL.createObjectURL(mediaStream)
但是這個方法即將在2018的12月被捨棄
所以我們改用另外一個方法
video.srcObject = mediaStream;
為了避免有寫瀏覽器不支援
所以我們使用try{} catch {}
來讓第一種方法不適用時
切換成第二種方法
這種方式寫起來更簡單
將HTMLMediaElement的srcobject屬性拿來存放MediaStream做其來源
最後用.play()播放video即可
不要忘了getVideo(),執行函式
這樣就可以得到攝像頭的影片了
接下來我們要將得到的影片畫到畫布上CanvasRenderingContext2D提供課多種方式在canvas上繪製圖像
其中一個語法是我們今天可以使用的
ctx.drawImage(image, dx, dy, dWidth, dHeight);
可以放canvas的圖像來源
如果單看MDN上的解釋,可能會一知半解
其實就是「從canvas的哪裡開始畫」
如果都是0的話
就是從左上角開始畫
在canvas上繪製的寬度/高度,允許對繪製的圖進行縮放
我們使用setInterval來更新我們的canvas
讓攝像頭拍到的影片能一直更新在canvas上
const canvas = document.querySelector('.photo');
const ctx = canvas.getContext('2d');
function paintToCanvas() {
const width = video.videoWidth;
const height = video.videoHeight;
//使canvas的像素等同於video的像素
canvas.width = width;
canvas.height = height;
//每16ms更新一次canvas
return setInterval(() => {
ctx.drawImage(video, 0, 0, width, height);
}, 16);
}
video.addEventListener('canplay', paintToCanvas);
再來就是拍照功能了
在按鈕被點擊後會觸發takePhoto()
首先先播放「喀嚓」的聲音吧
之前學過要播放聲音時
先設定.currentTime = 0
這樣才可以在短時間拍多張照片時
可以有多次喀嚓的聲音
<button onClick="takePhoto()">Take Photo</button>
const strip = document.querySelector('.strip');
const snap = document.querySelector('.snap');
function takePhoto() {
//play the sound
snap.currentTime = 0;
snap.play();
//設置圖片成dataURL的格式,存在網頁上
const data = canvas.toDataURL('image/jpeg');
//設置連結
const link = document.createElement('a');
link.href = data;
link.setAttribute('download', 'handsome');
link.innerHTML = `<img src="${data}" alt="Handsome Man">`
strip.insertBefore(link, strip.firstChild);
}
可以將圖片儲存在網頁上
語法
canvas.toDataURL(type, encoderOptions);
預設為image/png,可設定為image/jpeg
在image/jpeg或image/webp下,可以設定0~1,調整圖片的畫質
預設是0.92
並給他一個連結link,href指定到剛剛存圖片的(toDataURL)變數data
然後<a>的屬性download設置,可以使使用者點擊連結時,下載圖片
其值則是download的預設名稱
最後只要將link這個<a> innerHTML一個img
並使用insertBefore將他顯示在.strip上即可
語法
parentNode.insertBefore(newElement, referenceElement);
在參考的element前加入新的element
以上是如何擷取攝像頭的照片到canvas,並拍照下載
明天來替canvas上影像增加效果