[程式碼&DEMO] [HackMD完整筆記]
驅動webcam來紀錄影像資訊,再用cavas達成拍照與濾鏡效果。
預設的配置:
STEP0.建立一個localhost服務器
STEP1 取得影像
function getVideo() {
// 取得視訊裝置,回傳Promise狀態
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
//允許就把回傳的MediaStream寫進html的video tag中進行播放
.then(localMediaStream => {
console.log(localMediaStream);
video.srcObject = localMediaStream;
video.play();
})
//失敗就印出錯誤結果
.catch(err => {
console.error(`OH NO!!!`, err);
});
}
navigator.mediaDevices.getUserMedia()取得攝影鏡頭的權限。
返回一個promise對象。
STEP2 擷取視訊影像放到canvas中
function paintToCanvas() {
//設定畫布大小
const width = video.videoWidth;
const height = video.videoHeight;
canvas.width = width;
canvas.height = height;
/// 用setInterval來不斷地取得目前影像資訊
return setInterval(() => {
//將畫面擷取下來
ctx.drawImage(video, 0, 0, width, height);
//獲取canvas區域內的像素數據存進pixels變數中
let pixels = ctx.getImageData(0, 0, width, height);
//呼叫rgbSplit()把rgb像素分離
pixels = rgbSplit(pixels);
//將ImageData的數據繪製到圖像上
ctx.putImageData(pixels, 0, 0);
}, 16);
}
STEP3 製作拍照功能
function takePhoto() {
// 拍照的音效
snap.currentTime = 0;//音效從第0秒開始播放
snap.play();
// 用.toDataURL把canvas內容轉成base64的圖檔資訊
const data = canvas.toDataURL('image/jpeg');
//建立一個新的<a>元素
const link = document.createElement('a');
//設置連結位置為轉圖檔後的base64位置
link.href = data;
// 設置連結屬性為下載
link.setAttribute('download', 'handsome');
// 新增一個預覽圖
link.innerHTML = `<img src="${data}" alt="Handsome Man" />`;
//在圖片區插入新圖片(在第一筆的位置)
strip.insertBefore(link, strip.firstChild);
}
STEP4 製作濾鏡效果
function redEffect(pixels) {
//用迴圈將取回的所有像素資料全部跑一次,四個一組(r,g,b,alpha)
for (let i = 0; i < pixels.data.length; i+=4) {
pixels.data[i + 0] = pixels.data[i + 0] + 200; // RED
pixels.data[i + 1] = pixels.data[i + 1] - 50; // GREEN
pixels.data[i + 2] = pixels.data[i + 2] * 0.5; // Blue
}
return pixels;
}
把紅的項目加深處理,藍綠的項目-50及減半。
function rgbSplit(pixels) {
for (let i = 0; i < pixels.data.length; i+=4) {
pixels.data[i - 150] = pixels.data[i + 0]; // RED
pixels.data[i + 500] = pixels.data[i + 1]; // GREEN
pixels.data[i - 550] = pixels.data[i + 2]; // Blue
}
return pixels;
}
function greenScreen(pixels) {
const levels = {};
document.querySelectorAll('.rgb input').forEach((input) => {
levels[input.name] = input.value;
});
for (i = 0; i < pixels.data.length; i = i + 4) {
red = pixels.data[i + 0];
green = pixels.data[i + 1];
blue = pixels.data[i + 2];
alpha = pixels.data[i + 3];
if (red >= levels.rmin
&& green >= levels.gmin
&& blue >= levels.bmin
&& red <= levels.rmax
&& green <= levels.gmax
&& blue <= levels.bmax) {
// take it out!
pixels.data[i + 3] = 0;
}
}
return pixels;
}
語法:var promise = navigator.mediaDevices.getUserMedia(constraints);
建立一個帶有URL的DOMString,代表參數值中傳入的物件。此URL的生命週期與創造它的window一樣。