HTML Javascript๋ฅผ ์ด์ฉํด์ ์น์บ ์ ์ฌ์ฉํ๊ณ , ๋ค์ํ ํจ๊ณผ ์ ์ฉํด๋ณด๊ธฐ.
์ด๊ธฐ์ฝ๋
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Get User Media Code Along!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="photobooth">
<div class="controls">
<button onClick="takePhoto()">Take Photo</button>
<div class="rgb">
<label for="rmin">Red Min:</label>
<input type="range" min=0 max=255 name="rmin">
<label for="rmax">Red Max:</label>
<input type="range" min=0 max=255 name="rmax">
<br>
<label for="gmin">Green Min:</label>
<input type="range" min=0 max=255 name="gmin">
<label for="gmax">Green Max:</label>
<input type="range" min=0 max=255 name="gmax">
<br>
<label for="bmin">Blue Min:</label>
<input type="range" min=0 max=255 name="bmin">
<label for="bmax">Blue Max:</label>
<input type="range" min=0 max=255 name="bmax">
</div>
</div>
<canvas class="photo"></canvas>
<video class="player"></video>
<div class="strip"></div>
</div>
<audio class="snap" src="./snap.mp3" hidden></audio>
<script src="scripts.js"></script>
</body>
</html>
const video = document.querySelector('.player');
const canvas = document.querySelector('.photo');
const ctx = canvas.getContext('2d');
const strip = document.querySelector('.strip');
const snap = document.querySelector('.snap');
์ด๊ธฐ ํ๋ฉด
์์๋๋ก ๋ฐ๋ผ ์คํ ํ๋ค๊ฐ ๊ณ์ ์๋ฌ๊ฐ ๋ฐ์ํด FINISHED ์คํฌ๋ฆฝํธ๋ฅผ ๋ณด๋ chrome๊ณผ fireFox์์ ๋น์ถ์ฒํ๋ค๊ณ ์ ํ์์๋ค.
MDN์ createObjectURL์ ๋ค์ด๊ฐ ๋ณด๋ ๋ฏธ๋์ด ์คํธ๋ฆผ์ ๊ฐ์ฒดURL ์ฌ์ฉ ๋ถ๋ถ์์
๋ฏธ๋์ด ์์ค ์ฌ์์ ์ด์ ๋ฒ์ ์์๋ <video>
์์์ ์คํธ๋ฆผ์ ์ฒจ๋ถ ํ๋ ค๋ฉด MediaStream
์์์ ์คํธ๋ฆผ์ ์ฒจ๋ถ ํ๋ ค๋ฉด MediaStream
์์์ ์คํธ๋ฆผ์ ์ฒจ๋ถ ํ๋ ค๋ฉด MediaStream
์์์ ์คํธ๋ฆผ์ ์ฒจ๋ถ ํ๋ ค๋ฉด MediaStream
. ์ด๊ฒ์ ๋ ์ด์ ํ์ํ์ง ์์ผ๋ฉฐ ๋ธ๋ผ์ฐ์ ๋์ด๋ฅผ์ํ ์ง์์ ์ ๊ฑฐํ๊ณ ์์ต๋๋ค.
Important: If you still have code that relies on createObjectURL() to attach streams to media elements,
you need to update your code to set srcObject to the MediaStream directly.
๋ผ๊ณ ์ ํ ๊ฒ์ ํ์ธํ ์ ์๋ค.
video.srcObject = localMediaStream;
๋ก ๋ณ๊ฒฝํ๋ฉด ๋์ํ๊ฒ ๋๋ค.
์ฐธ๊ณ :
https://developer.mozilla. org/en-US/docs/Web/API/URL/createObjectURL
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/srcObject
takePhoto()๋ถ๋ถ์ ๋ฐ๋ผํ๋ค ๋ณด๋ฉด ์๋ ๋ฐ์ํ๊ฒ ๋๋ค.
GET http://localhost:3000/favicon.ico 404 (Not Found) error
favicon.ico๋ ๋ธ๋ผ์ฐ์ ํญ๋ถ๋ถ์์ ํ์ดํ ๋งจ ์ผ์ชฝ์ ์์ด์ฝ์ ๋งํ๋ค.
์์ด์ฝ์ด ์๊ฑฐ๋ ๊ฒฝ๋ก๊ฐ ๋ง์ง์์ ๋ฐ์ํ๋ ์ค๋ฅ๋ผ๊ณ ํ๋ค.
ํด๊ฒฐ๋ฐฉ๋ฒ :
html headํ๊ทธ์์ link๋ฅผ ์ถ๊ฐํด์ค.
<html>
<head>
<link rel="shortcut icon" href="#">
</head>
</html>
์ฐธ๊ณ :
https://cheonfamily.tistory.com/7 [์ฒ๋ฆฌ๊ธธ๋ ํ ๊ฑธ์๋ถํฐ]
๋ค์ด๋ก๋ ์ฐ๊ฒฐ ์ download attribute ์ฌ์ฉ.
๋ธ๋ผ์ฐ์ ์์ ์ด์ง ์ํน ๋ค์ด๋ก๋ํ ๋ฆฌ์์ค์ ์ฐ๊ฒฐํ๋ ๊ฒฝ์ฐ ๋ค์ด๋ก๋ ์์ฑ์ ์ฌ์ฉํ์ฌ ๊ธฐ๋ณธ ์ ์ฅ ํ์ผ ์ด๋ฆ์ ์ ๊ณตํ ์ ์๋ค.
[EX] Firefox 39์ Windows ๋ฒ์ ์ ๋ํ ๋ค์ด๋ก๋ ๋งํฌ๊ฐ ์๋ ์
<a href="https://download.mozilla.org/?product=firefox-39.0-SSL&os=win&lang=en-US"
download="firefox-39-installer.exe">
Download Firefox 39 for Windows
</a>
์ฐธ๊ณ :
https://developer.mozilla.org/ko/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks
const video = document.querySelector('.player');
const canvas = document.querySelector('.photo');
const ctx = canvas.getContext('2d');
const strip = document.querySelector('.strip');
const snap = document.querySelector('.snap');
video : ์ฐ์ธก์๋จ์ ๊ทธ๋ ค์ง video์์ญ
canvas : ํ๋ฉด ์๋์ video์์ญ์ ๋ณต์ฌํด ์ถ๋ ฅํ ๋ถ๋ถ.
ctx : canvas๋ฅผ ๊ฐ์ ธ์ฌ ๋ถ๋ถ.
strip : ์บก์ณ ํ ์ฌ์ง ๋ถ๋ถ์ด ๋ํ๋ ์์ญ
snap : ์ฌ์ง ์ฐ์ ๋ ์ฐฐ์นต ์๋ฆฌ๋๊ฒ ์ฌ์.
npm install
npm start
์์์ index.html์ด ์์๋จ.
function getVideo() {
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
.then(localMediaStream => {
console.log(localMediaStream);
// ํฌ๋กฌ,firefox์์ ๋น์ถ์ฒ
// video.src = window.URL.createObjectURL(localMediaStream);
video.srcObject = localMediaStream;
video.play();
}).catch(error => console.error(`OH NO!!! ` ,error));
}
getVideoํจ์์ ์ค์๊ฐ์ผ๋ก ์น์บ ์ ํ๋ฉด์ด ๋์ฌ ์ ์๋๋ก ๋ด์ฉ์ ์์ฑ.
์๋ฌ ๋ฐ์ ์ OH NO!!์ ์๋ฌ๋ฉ์ธ์ง๊ฐ ์ฝ์์ ์ฐํ.
getMedia์ ์ฝ์ ์ถ๋ ฅ๊ฒฐ๊ณผ.
function paintToCanvas() {
const width = video.videoWidth;
const height = video.videoHeight;
// console.log(width, height);
canvas.width = width;
canvas.height = height;
return setInterval(() => {
ctx.drawImage(video, 0, 0, width, height)
// take the pixels out
let pixels = ctx.getImageData(0, 0, width, height);
// mess with them - ํจ๊ณผ ๋ถ๋ถ.
// pixels = redEffect(pixels);
// pixels = rgbSplit(pixels);
// ctx.globalAlpha = 0.1;
// pixels = greenScreen(pixels);
// console.log(pixels);
// put them bakc
ctx.putImageData(pixels, 0, 0);
}, 16);
}
์บ๋ฒ์ค์ ์์ญ์ ์ง์ ํ๊ณ , video๋ฅผ ๊ทธ๋ฆฐ๋ค.
์ฌ์ง์ ์ฐ๋ ๋ฉ์๋
function takePhoto() {
// played the sound
snap.currentTime = 0;
snap.play();
// take the date out of the canvas
const data = canvas.toDataURL('image/jpeg');
const link = document.createElement('a');
link.href = data;
link.setAttribute('download', 'handsome');
// link.textContent = 'Download Image';
link.innerHTML = `<img src="${data}" alt="Handsome Man" />`;
strip.insertBefore(link, strip.firstChild);
console.log(data);
}
snap์ ์ฌ์์ํค๊ธฐ ๋๋ฌธ์ ์ด ๋ฉ์๋ ์คํ ์ ์ฌ์ง์๋ฆฌ๊ฐ ์ฌ์๋๋ค.
download์์ฑ์ ์ถ๊ฐํ์ฌ ์บก์ณ ์ ์ด๋ฏธ์ง๋ฅผ ์ ์ฅํจ.
์์ฑ๋ ๋งํฌ ์ด๋ฏธ์ง๋ค์ ์๋ strip์์ญ์ ์ถ๊ฐํ๋ค.
function redEffect(pixels) {
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;
}
pixels์ data์ red๋ถ๋ถ์ ๊ฐ์ ๋ถ๊ฒ ๋ง๋ค์ด ๋ถ์ ์คํฌ๋ฆฐ์ด ๋ํ๋๊ฒ ๋ง๋ฌ.
์์๋ณ๋ก ๋๋ ์ ธ์ ๋ณด์ด๊ฒ ํจ.
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 + 100] = pixels.data[i + 1]; // GREEN
pixels.data[i + 150] = pixels.data[i + 2]; // BLUE
}
return pixels;
}
function greenScreen(pixels) {
const levels = {};
document.querySelectorAll('.rgb input').forEach((input) => {
levels[input.name] = input.value;
});
// console.log(levels);
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;
}
rgb ๊ฐ์ ์ ํ์ ๋ .
context์ globalAlpha๊ฐ์ ์ฃผ์ด ์์ํจ๊ณผ๊ฐ ๋ํ๋๊ฒ๋จ.
return setInterval(() => {
ctx.drawImage(video, 0, 0, width, height)
// take the pixels out
let pixels = ctx.getImageData(0, 0, width, height);
// mess with them
// pixels = redEffect(pixels);
// pixels = rgbSplit(pixels);
ctx.globalAlpha = 0.1;
pixels = greenScreen(pixels);
// console.log(pixels);
// put them bakc
ctx.putImageData(pixels, 0, 0);
}, 16);
paintToCanvas()์์ setInterval๋ถ๋ถ์์ ์บ๋ฒ์ค๋ฅผ ๊ณ์๊ทธ๋ฆฌ๋๋ฐ
์ด ๋ pixels์ ํจ๊ณผ๋ฅผ ์ง์ ํด์ค๋ค.
return setInterval(() => {
ctx.drawImage(video, 0, 0, width, height)
// take the pixels out
let pixels = ctx.getImageData(0, 0, width, height);
// mess with them
// pixels = redEffect(pixels);
// pixels = rgbSplit(pixels);
// ctx.globalAlpha = 0.1;
pixels = greenScreen(pixels);
// console.log(pixels);
// put them bakc
ctx.putImageData(pixels, 0, 0);
}, 16);
getVideo();video.addEventListener('canplay', paintToCanvas);
โ ์ฉ๋๋ฌธ์ ๋ก ์ธํด GitHub์์ ๊ณผ์ ๋ณ ์คํํ๋ฉด์ ํ์ธ ํ ์ ์์ต๋๋ค.
https://github.com/JuneHyung/JavaScript30/blob/master/19%20-%20Webcam%20Fun/README.md