<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Videos</title>
<link rel="stylesheet" href="./styles.css"/>
</head>
<body>
<div class="controls">
<div class="rgb">
<label for="red">Red min</label>
<input type="range" name="rmin" min="0" max="255" />
<label for="red">Red máx</label>
<input type="range" name="rmax" min="0" max="255" />
<label for="green">Green min</label>
<input type="range" name="gmin" min="0" max="255" />
<label for="green">Green máx</label>
<input type="range" name="gmax" min="0" max="255" />
<label for="blue">Blue min</label>
<input type="range" name="bmin" min="0" max="255" />
<label for="blue">Blue máx</label>
<input type="range" name="bmax" min="0" max="255" />
</div>
<div class="toggle-filters">
<label for="toggleFilters">Red Filter</label>
<input type="radio" name="toggleFilters" value="redEffect">
<label for="toggleFilters">RGB Split</label>
<input type="radio" name="toggleFilters" value="rgbSplit">
<label for="toggleFilters">Green Screen</label>
<input type="radio" name="toggleFilters" value="greenScreen">
<label for="toggleFilters">No Filter</label>
<input type="radio" name="toggleFilters" value="noFilter" checked>
</div>
<input type="button" name="takeScreenshot" class="btn" value="Take Screenshot">
</div>
<div class="player">
<canvas id="canvas" width="640" height="480"></canvas>
<video width="640" height="480"></video>
</div>
<div class="screenshots"></div>
<script src="./scripts.js"></script>
</body>
</html>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
height: 100vh;
background: linear-gradient(to right, #4e54c8, #8f94fb);
}
.player {
height: 480px;
width: 640px;
position: relative;
}
video {
width: 160px;
height: 120px;
position: absolute;
top: -30px;
right: -30px;
z-index: 10;
}
canvas {
position: absolute;
z-index: 1;
background: #fff;
}
.screenshots {
margin: -100px 100px 0;
width: 90%;
height: 130px;
}
.screenshots img {
width: 120px;
padding: 12px 10px 30px;
box-shadow: 0 0 3px rgba(0,0,0,0.2);
background: white;
margin-right: 15px;
}
.controls {
width: 20vw;
margin-right: 80px;
margin-bottom: 20px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.controls .rgb {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 30px;
}
.controls .rgb * {
margin-bottom: 10px;
}
.controls > * {
margin: 5px 5px;
}
.controls .toggle-filters {
display: flex;
align-items: center;
text-align: center;
margin-bottom: 40px;
}
.btn {
width: 120px;
height: 30px;
background: #db0bcb;
color: #fff;
border-radius: 5px;
border: none;
outline: none;
}
.screenshots a:nth-child(5n+1) img { transform: rotate(10deg); }
.screenshots a:nth-child(5n+2) img { transform: rotate(-2deg); }
.screenshots a:nth-child(5n+3) img { transform: rotate(8deg); }
.screenshots a:nth-child(5n+4) img { transform: rotate(-11deg); }
.screenshots a:nth-child(5n+5) img { transform: rotate(12deg); }
@media screen and (max-width: 550px) {
body {
justify-content: space-around;
flex-direction: column;
}
canvas,
.player {
width: 280px;
height: 180px;
}
.player {
align-self: flex-end;
left: -30px;
}
video {
width: 120px;
height: 90px;
top: -20px;
right: -20px;
}
.controls {
width: 89vw;
margin: 0;
font-size: 14px;
}
.controls .rgb {
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
margin: 0;
}
.controls .rgb label {
width: 62px;
}
.controls .rgb input[type="range"] {
flex-direction: row;
flex-wrap: wrap;
margin: 0 10px;
}
.controls .toggle-filters {
margin: 0;
position: absolute;
top: 130px;
width: 120px;
align-self: flex-start;
flex-wrap: wrap;
}
.controls .toggle-filters label {
margin: 5px 10px 5px 0;
display: inline-block;
}
.controls .btn {
position: absolute;
top: 260px;
width: 120px;
align-self: flex-start;
margin: 0;
}
.screenshots {
height: 65px;
margin: 0;
}
.screenshots img {
width: 10%;
padding: 4px 6px 16px;
}
}
const canvas = document.querySelector('canvas'),
video = document.querySelector('video'),
screenshotButton = document.querySelector('input[name="takeScreenshot"]'),
context = canvas.getContext('2d');
function startCam() {
let media = navigator.mediaDevices.getUserMedia({ video: true, audio: false });
media.then(stream => {
video.srcObject = stream;
video.play();
})
.catch(error => console.log('Video could not be loaded', error));
}
function drawToCanvas() {
return setInterval(() => {
let width = video.width,
height = video.height;
context.drawImage(video, 0, 0, width, height);
let pixels = context.getImageData(0, 0, width, height);
pixels = setFilter(pixels);
context.putImageData(pixels, 0, 0);
}, 16);
}
function takeScreenshot() {
let screenshot = canvas.toDataURL('image/jpeg'),
link = document.createElement('a');
link.href = screenshot;
link.setAttribute('download', 'photo');
link.textContent = 'Download Image';
link.innerHTML = `<img src="${screenshot}" alt="Screenshot">`;
document.querySelector('.screenshots').append(link);
}
function redEffect(pixels) {
for (var i = 0; i < pixels.data.length; i += 4) {
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;
}
function rgbSplit(pixels) {
for (var i = 0; i < pixels.data.length; i += 4) {
pixels.data[i - 150] = pixels.data[i + 0];
pixels.data[i + 500] = pixels.data[i + 1];
pixels.data[i - 550] = pixels.data[i + 2];
}
return pixels;
}
function greenScreen(pixels) {
const levels = {};
document.querySelectorAll('.rgb input').forEach(input => {
levels[input.name] = input.value;
});
for (var i = 0; i < pixels.data.length; i++) {
let red = pixels.data[i + 0];
let green = pixels.data[i + 1];
let blue = pixels.data[i + 2];
let alpha = pixels.data[i + 3];
if (red >= levels.rmin
&& green >= levels.gmin
&& blue >= levels.bmin
&& red <= levels.rmax
&& green <= levels.gmax
&& blue <= levels.bmax) {
pixels.data[i + 3] = 0;
}
}
return pixels;
}
function setFilter(pixels) {
const filter = document.querySelector('.toggle-filters input:checked');
return filter.value == 'noFilter' ? pixels : window[filter.value](pixels);
}
startCam();
video.addEventListener('canplay', drawToCanvas);
screenshotButton.addEventListener('click', takeScreenshot);