JS Now Logo
Technology Logo

Creating a Real-Time QR Code Scanner With Vanilla JavaScript Part 2

Fletcher Rippon twitter profile
Fletcher Rippon@_fletcherrippon
Creating a Real-Time QR Code Scanner With Vanilla JavaScript Part 2 main image

Part One

This is part two of this article if you haven't read part one you can find it here.

In part one of the article, you will learn how to create the scanning functionality and learning how to access the camera to detect barcodes & QR codes in real-time.


What Will We Be Learing In Part Two

Now that we have created the barcode scanner in this of our project we will be learning how to create the outline around the code we are detecting/scanning and creating a previously scanned section that uses custom web components and proxies.

End Result

Want to use and see finalised project? here is a link to the live site


Why Are We Using Custom Web Components & Proxies?

Proxies

We will be using web proxies as a way to manage our projects state using proxies brings the benefit of being able to use getters and setters which act as an object on change event meaning we can tell out our applications state to run code whenever we get or set the state for this project.

We will only be using a setter for our proxy to check and see if the code has already been scanned and then append and display the QR code information in our custom web component.

Web Components

The reason we are using web components in this project is that it can help make code cleaner and easier to manage when using JavaScript to append elements to our document we will be reusing an HTML layout for every QR Code we scan so it makes sense to make this into a component that we can reuse.

Web components are typically considered to be a complex and difficult part of JavaScript to understand for this project, we will be only simply using them to give our component props so we can add dynamic data to each component easily.

All the code can be found on my GitHub if you run into any problems you can take a look through the code.

'Lets start coding!!'

Creating An Outline Around The Detected QR Code

Now that we have the scanner functionality let's make it so we can see the code being scanned in real-time this is a lot easier to be than you may think as the Barcode Detection API gives us all the data we need to create this outline.

The first thing we have to do is add a canvas element to cover over the top of our video element we will be using the HTML canvas to draw the outline of the QR Code over the our video element.

index.html
<!DOCTYPE html>
<html>
  <head>...</head>
  <body>
     
    <div id="scanner-wrapper">
      <canvas id="canvas" width="640" height="480"></canvas>
      <video id="video" width="640" height="480" autoplay></video>
    </div>
 
    <script src="./main.js" async></script>
  </body>
</html>

Now lets add some CSS styles to our canvas and scanner-wrapper to make the canvas lay on top of our video.

styles.css
#scanner-wrapper {
  height: 480px;
  position: relative;
  overflow: hidden;
}  
 
#canvas {
  position: absolute;
}

Now that we have an area to draw the outline of our code let's create the function to draw our outline.

I'm going to call my function drawCodePath() first thing we want to do is deconstruct the barcode object given to us by the BarcodeDetector API we are only going to be using the cornerPoints object in this function.

Inside of this function, the first thing we will be doing is selecting the canvas element from our HTML and getting the 2D context of the canvas.

We also are going to want to exit the function if there is no code detected and clear the canvas so if any code was detected previously we aren't left with an outline stuck on the screen at the last position a code was detected.

index.js
ctx.beginPath()
for (const [i, {x, y}] of cornerPoints.entries()) {
	  if (i === 0) {
	 	// Move to starting position first corner
	  	ctx.moveTo(x, y)
	  	continue
	  }
	  // Draw line from current pos to x, y
	  ctx.lineTo(x, y)
}
ctx.closePath()
ctx.stroke();

If you are looking at the code provided on my Github as a reference you will probably notice that this code for this section is very different and looks a lot more simple.

Don't worry the I will explain my old method of doing this, but I would recommend that you use the way described above purely because it is easier to read and understand.

Firstly I'll explain the new way of doing this than the previous way I found.

  • x and y in this loop represent the x and y corrodents of one corner of the code for the first corner in this loop we are going to move our starting point then continue to the next iteration. For every other corner, we are drawing a line starting from the top left corner then continuing clockwise.

  • beginPath method creates a starting point for our path that will be drawing any further drawing commands will be drawn as a single line or path.

  • lineTo(x, y) this method will draw a line on the canvas from your current x y position to the x y position parsed through the lineTo parameters.

  • moveTo(x, y) will move your current drawing point to an x y position on the canvas but will not draw a line between start and endpoints.

  • closePath method will end the current path that we are drawing and draw a straight line to the beginning of our path (beginPath).

Let's think about this as drawing a shape on paper, beginPath and moveTo methods are the actions of moving your pencil to your starting point then putting your pencil onto a piece of paper.

You can think of the lineTo method as the positions of where to move your pencil too.

Then the closePath method is drawing a connecting line from the endpoint to the starting point then taking your pencil off the paper.

The Old Way (On My GitHub Repo)

index.js
// Begin draw
ctx.beginPath();
 
// Draw code outline path
for (const [i, {x, y}] of cornerPoints.entries()) {
  if (i === 0) {
    // Move x half of the stroke width back 
    // makes the start and end corner line up
    ctx.moveTo(x - ctx.lineWidth/2, y);
    continue;
  }
 
  // Draw line from current pos to x, y
  ctx.lineTo(x, y);
 
  // Complete square draw to starting position
  if (i === cornerPoints.length-1) ctx.lineTo(cornerPoints[0].x, cornerPoints[0].y);
}
 
// Make path to stroke
ctx.stroke();

Now you have a functional QR code that can read QR codes data and highlight the codes in real-time. The rest of this article will show you how to create state management and display the codes data to a user.

These next two sections are optional to do and are not necessary if you have been creating this application in a framework such as React or Vue as they have their own state management built into them and their own ways of creating UI components.


Creating The State Management (Optional)


Displaying The QR Code Data To The User Using Custom Elements (Optional)

Support Us

Support us by donating to our Patreon or buy me a coffee to keep us writing