Skip to content

Commit 0b8a1dd

Browse files
Merge pull request #406 from rishabh217/Rishabh
Add Browser Camera App
2 parents 4f572c6 + 2f28a35 commit 0b8a1dd

File tree

5 files changed

+451
-0
lines changed

5 files changed

+451
-0
lines changed

Browser Camera/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<h1>Browser Camera App</h1>
2+
3+
<p>Simple Camera App written in HTML, CSS, and JavaScript which can be used to record and capture images.</p>
4+
5+
<h3>Used Technologies</h3>
6+
<ul>
7+
<li>HTML5</li>
8+
<li>CSS3</li>
9+
<li>JavaScript</li>
10+
</ul>
11+
12+
#### Steps to Use:
13+
14+
---
15+
16+
- Download or clone the repository
17+
18+
```
19+
git clone https://github.com/Ayushparikh-code/Web-dev-mini-projects.git
20+
```
21+
22+
- Go to the 'Browser Camera' directory
23+
- Run the index.html file
24+
- Start using the camera!!

Browser Camera/index.html

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
8+
<title>Camera</title>
9+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
10+
<link rel="stylesheet" href="style.css">
11+
</head>
12+
13+
<body>
14+
15+
<div class="video-container">
16+
<video autoplay></video>
17+
</div>
18+
<div class="ui-filter filter-6"></div>
19+
20+
<div class="filter-container">
21+
<div class="filter filter-1"></div>
22+
<div class="filter filter-2"></div>
23+
<div class="filter filter-3"></div>
24+
<div class="filter filter-4"></div>
25+
<div class="filter filter-5"></div>
26+
<div class="filter filter-6"></div>
27+
</div>
28+
29+
<div class="timing-container"><div class="timing">00:00:00</div></div>
30+
31+
<div class="zoom-container">
32+
<i class="fas fa-plus icon"></i>
33+
<i class="fas fa-minus icon"></i>
34+
</div>
35+
36+
<div class="button-container">
37+
<div class="record"><button id="record-video"></button></div>
38+
<div class="click"><button id="click-image"></button></div>
39+
</div>
40+
41+
<!-- <div class="gallery-container">
42+
<a href="gallery.html" class="gallery"><i class="fab fa-envira"></i></a>
43+
</div> -->
44+
45+
<script src="indexedDBScript.js" defer></script>
46+
<script src="script.js" defer></script>
47+
</body>
48+
49+
</html>

Browser Camera/indexedDBScript.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
let request = indexedDB.open("camera", 1);
2+
let db;
3+
4+
request.onsuccess = function () {
5+
// if exist then will get db from here
6+
db = request.result;
7+
}
8+
request.onerror = function (err) {
9+
console.log(err)
10+
}
11+
request.onupgradeneeded = function () {
12+
// 1st time creation
13+
db = request.result;
14+
db.createObjectStore("images", { keyPath: "mid" });
15+
db.createObjectStore("videos", { keyPath: "mid" });
16+
}
17+
18+
/* function addMediaToDB(data, table) {
19+
if (db) {
20+
// you need to get transaction
21+
let tx = db.transaction(table, "readwrite");
22+
// get table refer
23+
let store = tx.objectStore(table);
24+
// add
25+
store.add({ mid: Date.now(), media: data });
26+
27+
} else {
28+
alert("db is loading")
29+
}
30+
} */

Browser Camera/script.js

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
let video = document.querySelector("video");
2+
3+
let constraints = {
4+
video: true,
5+
audio: true
6+
};
7+
8+
let mediaRecorder;
9+
let buffer = [];
10+
11+
let recordState = false;
12+
13+
let videoRecorder = document.querySelector("#record-video");
14+
let captureButton = document.querySelector("#click-image");
15+
16+
let timingELem = document.querySelector(".timing");
17+
let clearObj;
18+
19+
let allFilters = document.querySelectorAll(".filter");
20+
let uiFilter = document.querySelector(".ui-filter");
21+
22+
let zoomIn = document.querySelector(".fa-plus");
23+
let zoomOut = document.querySelector(".fa-minus");
24+
25+
let scale = 1.0;
26+
27+
// Video recorder listeners
28+
navigator.mediaDevices
29+
.getUserMedia(constraints)
30+
.then(function (mediaStream) {
31+
video.srcObject = mediaStream;
32+
33+
mediaRecorder = new MediaRecorder(mediaStream);
34+
mediaRecorder.addEventListener('dataavailable', function (e) {
35+
buffer.push(e.data);
36+
});
37+
mediaRecorder.addEventListener('stop', function () {
38+
let blob = new Blob(buffer, { type: "video/mp4" });
39+
const url = window.URL.createObjectURL(blob);
40+
let a = document.createElement("a");
41+
a.download = `VID_${getTimeStamp()}.mp4`;
42+
a.href = url;
43+
a.click();
44+
a.remove();
45+
addMediaToDB(url, "videos");
46+
buffer = [];
47+
});
48+
}).catch(function (err) {
49+
console.log(err);
50+
});
51+
52+
// Recording Video
53+
videoRecorder.addEventListener('click', function () {
54+
if (!mediaRecorder) {
55+
alert("Permissions not given");
56+
return;
57+
}
58+
if (!recordState) {
59+
mediaRecorder.start();
60+
videoRecorder.style.animation = "buttonAnimation 0.75s infinite";
61+
recordState = true;
62+
startClock();
63+
} else {
64+
mediaRecorder.stop();
65+
videoRecorder.style.animation = "none";
66+
recordState = false;
67+
stopClock();
68+
}
69+
});
70+
71+
// Capturing Image
72+
captureButton.addEventListener("click", function () {
73+
if (!mediaRecorder) {
74+
alert("Permissions not given");
75+
return;
76+
}
77+
// Create a canvas element equal to video frame
78+
let canvas = document.createElement("canvas");
79+
canvas.width = video.videoWidth;
80+
canvas.height = video.videoHeight;
81+
let tool = canvas.getContext("2d");
82+
// Zoom from center
83+
tool.scale(scale, scale);
84+
let x = (tool.canvas.width / scale - video.videoWidth) / 2;
85+
let y = (tool.canvas.height / scale - video.videoHeight) / 2;
86+
// Draw a frame on that canvas
87+
tool.drawImage(video, x, y);
88+
// translucent
89+
tool.globalAlpha = 0.25;
90+
tool.fillStyle = getFilter(document.querySelector(".ui-filter").classList[1]);
91+
// things are drawn on above layer
92+
tool.fillRect(0, 0, canvas.width, canvas.height);
93+
// toDataUrl
94+
let link = canvas.toDataURL();
95+
// Download
96+
let anchor = document.createElement("a");
97+
anchor.href = link;
98+
anchor.download = `IMG_${getTimeStamp()}.png`;
99+
anchor.click();
100+
anchor.remove();
101+
canvas.remove();
102+
addMediaToDB(link, "images");
103+
captureButton.style.animation = "buttonAnimation 0.5s 1";
104+
setTimeout(() => {
105+
captureButton.style.animation = "none";
106+
}, 1000);
107+
});
108+
109+
// Get current time stamp for file name
110+
function getTimeStamp() {
111+
return new Date().getTime();
112+
}
113+
114+
// Filter helper
115+
function getFilter(filter) {
116+
switch (filter) {
117+
case "filter-1": return "#cc3838ad";
118+
case "filter-2": return "#0fbbbbad";
119+
case "filter-3": return "#8ddb18ad";
120+
case "filter-4": return "#ee82eead";
121+
case "filter-5": return "#b8870bad";
122+
case "filter-6": return "#ffffff00";
123+
}
124+
}
125+
126+
// Video Recorder Timers
127+
function startClock() {
128+
timingELem.classList.add("timing-active");
129+
let timeCount = 0;
130+
clearObj = setInterval(function () {
131+
let seconds = (timeCount % 60) < 10 ? `0${timeCount % 60}` : `${timeCount % 60}`;
132+
let minutes = (timeCount / 60) < 10 ? `0${Number.parseInt(timeCount / 60)}` : `${Number.parseInt(timeCount / 60)}`;
133+
let hours = (timeCount / 3600) < 10 ? `0${Number.parseInt(timeCount / 3600)}` : `${Number.parseInt(timeCount / 3600)}`;
134+
timingELem.innerText = `${hours}:${minutes}:${seconds}`;
135+
timeCount++;
136+
}, 1000);
137+
}
138+
function stopClock() {
139+
timingELem.classList.remove("timing-active");
140+
timingELem.innerText = "00:00:00";
141+
clearInterval(clearObj);
142+
}
143+
144+
// Filter apply
145+
for (let i = 0; i < allFilters.length; i++) {
146+
allFilters[i].addEventListener("click", function () {
147+
uiFilter.classList.remove(uiFilter.classList[1]);
148+
uiFilter.classList.add(allFilters[i].classList[1]);
149+
})
150+
}
151+
152+
// Zoom apply
153+
zoomIn.addEventListener("click", function () {
154+
if (scale > 1.9)
155+
return;
156+
scale += 0.1;
157+
// -x for mirroring
158+
video.style.transform = `scale(-${scale}, ${scale})`;
159+
})
160+
zoomOut.addEventListener("click", function () {
161+
if (scale < 0.5)
162+
return;
163+
scale -= 0.1;
164+
// -x for mirroring
165+
video.style.transform = `scale(-${scale}, ${scale})`;
166+
})

0 commit comments

Comments
 (0)