Description:
For this tutorial we will be using Vite, vite is a development tool that allows us to have almost zero configuration and start coding rigth away. We will cover some known javascript events to build this app.
I hope you enjoy it π€
- Open a terminal and go to your preferred folder
- Run the following command:
npm create vite@latest - Select the following options:

- Go to
photo-boothfolder and run:npm install - Once the installation is completed, lets run:
npm run dev - Go to: localhost
- If eveything went well, you should be able to see the following screen:

- Open the photo-booth app folder in Visual studio code.
- Go to
index.html - Change the title tag to:
Photo Booth - oriente.dev - Remove the following div:
<div id="app"></div> - Go to
main.jsand Clear all the content from it - Go to
style.cssand clear all the content from it
We will have a section to wrap our photo booth app, and 4 more sections inside. Lets' break them in different items so we can go through all of them:
- Go to
index.html - Add a new section above the script tag:
<section class="app-container"></section> - Inside of the
app-containersections, lets add a new tag for the app title:<h1>Photo Booth oriente.dev</h1> - Then, lets add the video container with the button that will help us see our camera and take a photo of ourselves:
<section class="video-container">
<video id="video" autoplay></video>
<div class="button-container">
<button id="capture-btn">Snap!</button>
</div>
</section>- Now, we will add an empty section to append all images that we will be taking:
<section id="images-container">
<!-- Images are rendered here -->
</section>- And last but not least, we will be adding a hidden canvan element, that will allow us to actually create an image out of the video that it's streaming from the camera.
<!-- not displayed in the web page -->
<canvas
id="canvas"
width="640"
height="480"
style="display: none"
></canvas>The result that we should be getting now is the following page:
Hint: Here's the entire HTML file, just in case you migth be missing something:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Photo Booth - oriente.dev</title>
</head>
<body>
<section class="app-container">
<h1>Photo Booth oriente.dev</h1>
<section class="video-container">
<video id="video" autoplay></video>
<div class="button-container">
<button id="capture-btn">Snap!</button>
</div>
</section>
<section id="images-container">
<!-- Images are rendered here -->
</section>
<!-- not displayed in the web page -->
<canvas
id="canvas"
width="640"
height="480"
style="display: none"
></canvas>
</section>
<script type="module" src="/main.js"></script>
</body>
</html>- Go to
main.js - We will need to create 4 constants and access our DOM elements from there. To do that in the root of the main folder we will add the following code:
const video = document.getElementById("video");
const canvas = document.getElementById("canvas");
const captureButton = document.getElementById("capture-btn");
const imagesContainer = document.getElementById("images-container");- We will add ours first event which is
DOMContentLoaded, which basically gets executed when the DOM finished loading all of the HTML elements. Here's how we will add the event listener:
async function initCamera() {
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
video.srcObject = stream;
} catch (err) {
console.error("Error accessing the camera: ", err);
}
}
// Initialize camera when the page loads
window.addEventListener("DOMContentLoaded", initCamera);Once we do this, we should be able to go to our page and see the following:
- Now, we will add a new event to the button, to actually take a photo out of the video that's currently streaming. To do so, we need to use the canvas and create a new Image element that we will append to the view.
// Capture image when the button is clicked
captureButton.addEventListener("click", captureImage);
// Capture a still image
function captureImage() {
const context = canvas.getContext("2d");
context.drawImage(video, 0, 0, canvas.width, canvas.height);
// Convert canvas to image
const imgData = canvas.toDataURL("image/png");
// Display image
const capturedImage = new Image();
capturedImage.src = imgData;
capturedImage.width = "200";
capturedImage.height = "150";
imagesContainer.prepend(capturedImage);
}I will explain above code more in details in our meetup practical session. but what we are doing is that we are taking an screenshot of the video using the canvas context and then transforming that to a image in data format.
Then we create an HTML tag by using the new Image() constructor, and finally we are appending the new image to the imagesContainer section.
- If you go to our localhost web page, and see the video, then click on the button called: "Snap", you should see something like this:
Now, we have seen how to add interactivity to a web page using javascript, we can see how powerful javascript is, and what it allows us to do using events. We only covered 2 events and now we were able to build a photo booth app, just as simple as it looks like.
Here's the MDN documentation to check more events: MDN Events
We have a decent application so far, but it looks a little bit uggly. So we want to add some styles to it.
-
Go to
main.jsand add import the style fileimport "./style.css";stylesheet. -
Go to
style.cssfile and add the following styles:
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
background-color: #212121;
color: white;
}
h1 {
font-size: 50px;
text-align: center;
}
.app-container {
display: flex;
flex-flow: column;
margin: 0 auto;
max-width: 768px;
align-items: center;
}
.video-container {
border-radius: 16px;
width: 440px;
border: 2px solid white;
}
.video-container > video {
height: 327px;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
.button-container {
width: 100%;
border-top: 2px solid white;
display: flex;
align-items: center;
justify-content: center;
}
.button-container > button {
background: #474747;
border: none;
cursor: pointer;
color: white;
font-size: 24px;
width: 100%;
padding: 8px;
border-bottom-left-radius: 16px;
border-bottom-right-radius: 16px;
}
#images-container {
display: flex;
flex-flow: row;
gap: 8px;
border: 2px solid white;
min-height: 150px;
width: 440px;
margin: 40px 0;
overflow-x: auto;
padding: 8px;
}
#images-container::-webkit-scrollbar {
display: none;
}Note: I won't take a lot of time explaining what every line of css does, but I will go through some of them in our meetup.
Here's the final result of our app:
Thanks for bearing with us, stay tuned for future content.
