forked from Ayushparikh-code/Web-dev-mini-projects
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4f572c6
commit b8ce06b
Showing
5 changed files
with
451 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<h1>Browser Camera App</h1> | ||
|
||
<p>Simple Camera App written in HTML, CSS, and JavaScript which can be used to record and capture images.</p> | ||
|
||
<h3>Used Technologies</h3> | ||
<ul> | ||
<li>HTML5</li> | ||
<li>CSS3</li> | ||
<li>JavaScript</li> | ||
</ul> | ||
|
||
#### Steps to Use: | ||
|
||
--- | ||
|
||
- Download or clone the repository | ||
|
||
``` | ||
git clone https://github.com/Ayushparikh-code/Web-dev-mini-projects.git | ||
``` | ||
|
||
- Go to the 'Browser Camera' directory | ||
- Run the index.html file | ||
- Start using the camera!! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Camera</title> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"> | ||
<link rel="stylesheet" href="style.css"> | ||
</head> | ||
|
||
<body> | ||
|
||
<div class="video-container"> | ||
<video autoplay></video> | ||
</div> | ||
<div class="ui-filter filter-6"></div> | ||
|
||
<div class="filter-container"> | ||
<div class="filter filter-1"></div> | ||
<div class="filter filter-2"></div> | ||
<div class="filter filter-3"></div> | ||
<div class="filter filter-4"></div> | ||
<div class="filter filter-5"></div> | ||
<div class="filter filter-6"></div> | ||
</div> | ||
|
||
<div class="timing-container"><div class="timing">00:00:00</div></div> | ||
|
||
<div class="zoom-container"> | ||
<i class="fas fa-plus icon"></i> | ||
<i class="fas fa-minus icon"></i> | ||
</div> | ||
|
||
<div class="button-container"> | ||
<div class="record"><button id="record-video"></button></div> | ||
<div class="click"><button id="click-image"></button></div> | ||
</div> | ||
|
||
<!-- <div class="gallery-container"> | ||
<a href="gallery.html" class="gallery"><i class="fab fa-envira"></i></a> | ||
</div> --> | ||
|
||
<script src="indexedDBScript.js" defer></script> | ||
<script src="script.js" defer></script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
let request = indexedDB.open("camera", 1); | ||
let db; | ||
|
||
request.onsuccess = function (e) { | ||
// if exist then will get db from here | ||
db = request.result; | ||
} | ||
request.onerror = function (err) { | ||
console.log(err) | ||
} | ||
request.onupgradeneeded = function () { | ||
// 1st time creation | ||
db = request.result; | ||
db.createObjectStore("images", { keyPath: "mid" }); | ||
db.createObjectStore("videos", { keyPath: "mid" }); | ||
} | ||
|
||
function addMediaToDB(data, table) { | ||
if (db) { | ||
// you need to get transaction | ||
let tx = db.transaction(table, "readwrite"); | ||
// get table refer | ||
let store = tx.objectStore(table); | ||
// add | ||
store.add({ mid: Date.now(), media: data }); | ||
|
||
} else { | ||
alert("db is loading") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
let video = document.querySelector("video"); | ||
|
||
let constraints = { | ||
video: true, | ||
audio: true | ||
}; | ||
|
||
let mediaRecorder; | ||
let buffer = []; | ||
|
||
let recordState = false; | ||
|
||
let videoRecorder = document.querySelector("#record-video"); | ||
let captureButton = document.querySelector("#click-image"); | ||
|
||
let timingELem = document.querySelector(".timing"); | ||
let clearObj; | ||
|
||
let allFilters = document.querySelectorAll(".filter"); | ||
let uiFilter = document.querySelector(".ui-filter"); | ||
|
||
let zoomIn = document.querySelector(".fa-plus"); | ||
let zoomOut = document.querySelector(".fa-minus"); | ||
|
||
let scale = 1.0; | ||
|
||
// Video recorder listeners | ||
navigator.mediaDevices | ||
.getUserMedia(constraints) | ||
.then(function (mediaStream) { | ||
video.srcObject = mediaStream; | ||
|
||
mediaRecorder = new MediaRecorder(mediaStream); | ||
mediaRecorder.addEventListener('dataavailable', function (e) { | ||
buffer.push(e.data); | ||
}); | ||
mediaRecorder.addEventListener('stop', function (e) { | ||
let blob = new Blob(buffer, { type: "video/mp4" }); | ||
const url = window.URL.createObjectURL(blob); | ||
let a = document.createElement("a"); | ||
a.download = `VID_${getTimeStamp()}.mp4`; | ||
a.href = url; | ||
a.click(); | ||
a.remove(); | ||
addMediaToDB(url, "videos"); | ||
buffer = []; | ||
}); | ||
}).catch(function (err) { | ||
console.log(err); | ||
}); | ||
|
||
// Recording Video | ||
videoRecorder.addEventListener('click', function () { | ||
if (!mediaRecorder) { | ||
alert("Permissions not given"); | ||
return; | ||
} | ||
if (!recordState) { | ||
mediaRecorder.start(); | ||
videoRecorder.style.animation = "buttonAnimation 0.75s infinite"; | ||
recordState = true; | ||
startClock(); | ||
} else { | ||
mediaRecorder.stop(); | ||
videoRecorder.style.animation = "none"; | ||
recordState = false; | ||
stopClock(); | ||
} | ||
}); | ||
|
||
// Capturing Image | ||
captureButton.addEventListener("click", function () { | ||
if (!mediaRecorder) { | ||
alert("Permissions not given"); | ||
return; | ||
} | ||
// Create a canvas element equal to video frame | ||
let canvas = document.createElement("canvas"); | ||
canvas.width = video.videoWidth; | ||
canvas.height = video.videoHeight; | ||
let tool = canvas.getContext("2d"); | ||
// Zoom from center | ||
tool.scale(scale, scale); | ||
let x = (tool.canvas.width / scale - video.videoWidth) / 2; | ||
let y = (tool.canvas.height / scale - video.videoHeight) / 2; | ||
// Draw a frame on that canvas | ||
tool.drawImage(video, x, y); | ||
// translucent | ||
tool.globalAlpha = 0.25; | ||
tool.fillStyle = getFilter(document.querySelector(".ui-filter").classList[1]); | ||
// things are drawn on above layer | ||
tool.fillRect(0, 0, canvas.width, canvas.height); | ||
// toDataUrl | ||
let link = canvas.toDataURL(); | ||
// Download | ||
let anchor = document.createElement("a"); | ||
anchor.href = link; | ||
anchor.download = `IMG_${getTimeStamp()}.png`; | ||
anchor.click(); | ||
anchor.remove(); | ||
canvas.remove(); | ||
addMediaToDB(link, "images"); | ||
captureButton.style.animation = "buttonAnimation 0.5s 1"; | ||
setTimeout(() => { | ||
captureButton.style.animation = "none"; | ||
}, 1000); | ||
}); | ||
|
||
// Get current time stamp for file name | ||
function getTimeStamp() { | ||
return new Date().getTime(); | ||
} | ||
|
||
// Filter helper | ||
function getFilter(filter) { | ||
switch (filter) { | ||
case "filter-1": return "#cc3838ad"; | ||
case "filter-2": return "#0fbbbbad"; | ||
case "filter-3": return "#8ddb18ad"; | ||
case "filter-4": return "#ee82eead"; | ||
case "filter-5": return "#b8870bad"; | ||
case "filter-6": return "#ffffff00"; | ||
} | ||
} | ||
|
||
// Video Recorder Timers | ||
function startClock() { | ||
timingELem.classList.add("timing-active"); | ||
let timeCount = 0; | ||
clearObj = setInterval(function () { | ||
let seconds = (timeCount % 60) < 10 ? `0${timeCount % 60}` : `${timeCount % 60}`; | ||
let minutes = (timeCount / 60) < 10 ? `0${Number.parseInt(timeCount / 60)}` : `${Number.parseInt(timeCount / 60)}`; | ||
let hours = (timeCount / 3600) < 10 ? `0${Number.parseInt(timeCount / 3600)}` : `${Number.parseInt(timeCount / 3600)}`; | ||
timingELem.innerText = `${hours}:${minutes}:${seconds}`; | ||
timeCount++; | ||
}, 1000); | ||
} | ||
function stopClock() { | ||
timingELem.classList.remove("timing-active"); | ||
timingELem.innerText = "00:00:00"; | ||
clearInterval(clearObj); | ||
} | ||
|
||
// Filter apply | ||
for (let i = 0; i < allFilters.length; i++) { | ||
allFilters[i].addEventListener("click", function () { | ||
uiFilter.classList.remove(uiFilter.classList[1]); | ||
uiFilter.classList.add(allFilters[i].classList[1]); | ||
}) | ||
} | ||
|
||
// Zoom apply | ||
zoomIn.addEventListener("click", function () { | ||
if (scale > 1.9) | ||
return; | ||
scale += 0.1; | ||
// -x for mirroring | ||
video.style.transform = `scale(-${scale}, ${scale})`; | ||
}) | ||
zoomOut.addEventListener("click", function () { | ||
if (scale < 0.5) | ||
return; | ||
scale -= 0.1; | ||
// -x for mirroring | ||
video.style.transform = `scale(-${scale}, ${scale})`; | ||
}) |
Oops, something went wrong.