0%

JavaScript30-Java-script-Webcam-Fun-19

這篇大概是花最多時間做的一篇作品,
把他沒有做的功能都自己延伸出來,
沒想到可以這麼廢寢忘食,
從一開始最簡單的色塊,變成圖像位移,

然後成功建立出可以download照片,
最後也把去被效果寫出來,
再把他們變成可以隨意切換,
收穫很大的一個作品,
也不知道突然怎麼了變的這麼有動力,

最近覺得每天都過得好快,也每天都變得很慢(?
快好像是心情上的愉悅,慢好像是比以前又做更多的事情,學了更多的東西,
想不到是什麼讓我突然變了樣。 唯一想到的只有一個可能
是變年輕了吧

有些很在意的事情,慢慢的就不會再去想它了,
有些不好的記憶也被取代了,
真的是幸運,今年的運氣應該都用上了,

但也太快了,也像上了癮,
還以為自己是一個慢慢來的人,
沒想到成癮真的像嗑藥一樣,
令人瘋狂且著迷,

算算時間改變開始也過了一個月,
感覺好像該戒斷了,
應該是一個自制力很好的人,
戒斷反應就算來的很快,我應該也是可以承受得住吧,

反正會在你身邊的人就是會,
會錯過的怎麼留都是會走,
放了才能夠快樂 讓心好好休息一下 握不住的砂放下也罷。
不知道放下是不是真的會快樂一點,
但其實現在好像更快樂一點,

就像你說的,想著麼多的人生很無趣,
沒有人會知道下一步會發生什麼這樣才好玩,

優柔寡斷,倔將又容易妥協,
不知道什麼時候我變成這樣了,

到現在還是沒有一個明確的方向,反正過一天算一天,
就算真的有機會了,
我想我也不會願意踏出那一步,

覺得這樣的自己跟原本有的道德觀好不一樣,
江山易改本性難移根本是騙人了,
那是因為大家都沒有遇到真的可以讓你們不計較利益損失的夢想,
所以才會覺得安逸是一件比較好的事情吧,

雖然曾經我也不覺得自己是會想都不想就跳出舒適圈的人,
但好像真的遇到非你不可的狀況,
我會這樣做選擇,
沒想到這樣也可以多學到一課人生的方向,

當下次又有面臨抉擇的時候,
應該就可以用這個方向,去選擇人生的道路了,
反正未來的事沒有人說得準。

只要現在很開心,就好了吧。

其實很慶幸,可以這樣走出來,
完全不帶一點遺憾,
完完全全釋懷的心境。
好像又把自己提升倒立一個維度了,
加油吧,未來的都每一秒,都要變得更好的人,
希望再這樣下去可以擺脫,
心裡一直以來的的標籤,
也許大家不這麼覺得,
但自己不信也沒辦法服自己,
從現在開始,做一個相信自己也是很好的人。

19 - Webcam Fun

首次上傳:2020/12/2

主題

利用navigator.mediaDevices.getUserMedia來取得視訊鏡頭影像,並透過cavas來達到拍照與濾鏡的效果。

步驟

Step1. 啟動Local Server

這個練習需要使用到local server,
如果你已經有一個可在本機run起來的server可以直接使用,
或在這層資料夾底下運行npm install來安裝browser-sync
安裝完成後可以透過指令npm start來啟動localserver(預設port3000),

npm指令需要下載node.js來使用

Step2. 取得影像

透過navigator.mediaDevices.getUserMedia來取得視訊影像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function getVideo() {
// 取得user的視訊裝置,回傳Promise狀態
navigator.mediaDevices.getUserMedia({
video: true,
audio: false
})
// 如果允許則把回傳的MediaStream寫進html的video tag中並播放
.then(localMediaStream => {
/* console.log(localMediaStream); */
video.src = window.URL.createObjectURL(localMediaStream);
video.play();
})
// 當失敗時印出錯誤結果
.catch(err => {
console.error(`ERROR: `, err);
})
}

參閱:MDN-MediaDevices.getUserMedia()

Step3. 取得視訊資料並輸出在cavas區塊中

1
2
3
4
5
6
7
8
9
10
11
12
function paintToCanavas() {
// 設置寬高
const width = video.videoWidth;
const height = video.videoHeight;
canvas.width = width;
canvas.height = height;
// 用setInterval來持續取得目前的影像資訊
return setInterval(() => {
// 在canvas中設置內容來源與video相同,並且X、Y軸及長寬與video相同
ctx.drawImage(video, 0, 0, width, height);
}, 16)
}

參閱:MDN-CanvasRenderingContext2D.drawImage()

Step4. 製作拍照功能!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function takePhoto() {
// 拍照的音效->把音效切到第0秒並播放
snap.currentTime = 0;
snap.play();
// 利用toDataURL把canvas的內容轉為base64的圖檔資訊
const data = canvas.toDataURL('image/jpeg');
// 用createElemamnt來建立一個新的a元素
const link = document.createElement('a');
// 設置連結位置為轉圖檔後的base64位置
link.href = data;
// 設置連結為下載
link.setAttribute('download', 'photo');
// 內部新增一個預覽圖
link.innerHTML = `<img src="${data}" alt="photo" />`;
// 在圖片區塞入新圖片(在第一筆的位置)
strip.insertBefore(link, strip.firstChild);
}

參閱:MDN-HTMLCanvasElement.toDataURL()
參閱:MDN-Node.insert Before()

Step5. 濾鏡效果(紅色)

再回到Step3的paintToCanavas()中新增:

1
2
3
4
5
6
7
8
9
10
11
12
function paintToCanavas() {
// ...略
return setInterval(() => {
ctx.drawImage(video, 0, 0, width, height);
// 透過getImageData取得當前canvans中所有的像素點(r,g,b,alpha的資訊)
let pixels = ctx.getImageData(0, 0, width, height);
// 製作效果
pixels = redEffect(pixels); // 紅色濾鏡效果
// 置入效果
ctx.putImageData(pixels, 0, 0);
}, 16)
}

並新增一個對應的濾鏡functionredEffect()

1
2
3
4
5
6
7
8
9
10
function redEffect(pixels) {
// 透過迴圈將取回的所有像素資料跑一次,i +=4 是因為四個一組(r,g,b,alpha)
for (let i = 0; i < pixels.data.length; i += 4) {
// 下面組合就是單純把R(紅色)增強達到紅色濾鏡的效果
pixels.data[i + 0] = pixels.data[i + 0] + 100;
pixels.data[i + 1] = pixels.data[i + 1] - 50;
pixels.data[i + 2] = pixels.data[i + 2] * 0.5;
}
return pixels;
}

參閱:MDN-CanvasRenderingContext2D.getImageData()
參閱:MDN-putImageData()

[DEMO]