Skip to content

How do i generate qr code from url in javascript

so i building a url shortner which takes the url from python and generates a QR code in along with the shortUrl, i am using jinja2template for the UI, as i am very new to JavaScript the below code is mostly copied from Youtube and Internet.

This is the class which will show the converted shortUrl and will have a copy link button next o it

            <div class = "result__container">
                <div class = "shorturl">
                    <div id="qrcode"></div>
                </div>
                <div>
                    <button onclick = "copyLink()">Copy Link</button>

                </div>
            </div>

This is the logic create the qr code I am using qrcode.min.js here to create the qrcode

    <script src="https://cdn.jsdelivr.net/gh/davidshimjs/qrcodejs/qrcode.min.js"></script>

    <script>
        const qrcode = new QRCode(document.getElementById('qrcode'), {
            text: response.shortUrl,
            width: 128,
            height: 128,
            colorDark : '#000',
            colorLight : '#fff',
            correctLevel : QRCode.CorrectLevel.H
    });

            xhr.onload = function () {
                const response = JSON.parse(this.responseText);
                console.log(this.status);
                console.log(response);
                if(this.status ==200){
                    resultContainer.style.display = "flex";
                    shortUrl.innerHTML = `SHORT URL :- <a href=${response.shortUrl}>${response.shortUrl}</a>`
                }
                else{
                    alert(`An error occurred, ${response.detail}`)
                }
            };

Answer

This simple library by David Shim makes it easy!

const qrcode = new QRCode(document.getElementById('qrcode'), {
  text: 'http://jindo.dev.naver.com/collie',
  width: 128,
  height: 128,
  colorDark : '#000',
  colorLight : '#fff',
  correctLevel : QRCode.CorrectLevel.H
});
<script src="https://cdn.jsdelivr.net/gh/davidshimjs/qrcodejs/qrcode.min.js"></script>

<div id="qrcode"></div>

You can also get really fancy with your styling and actions. here is an example I built using the same foundational code. After styling the QR code and document, I added three action buttons on hover which will download, copy, or visit the QR/source accordingly. Unfortunately, these buttons do not work in iframes due to permission issues, so they will not function in the StackOverflow snippet, or on CodePen, JSFiddle, CodeSandbox, etc. However, you can load this code into your own server to see it all work perfectly.

Here is the finished product:

const qrElement = document.getElementById('qrcode');

const qrUrl = 'https://davidshimjs.github.io/qrcodejs/';

const qrcode = new QRCode(document.getElementById('qrcode'), {
  text: qrUrl,
  width: 128,
  height: 128,
  colorDark : '#000',
  colorLight : '#fff',
  correctLevel : QRCode.CorrectLevel.H
});

const qrActionButtons = Array.from(qrElement.querySelectorAll('.qr-action'));

qrActionButtons.find(b => b.dataset.qrAction === 'visit').href = qrUrl;

document.addEventListener('click', e => {
  if (e.target) {
    if (qrActionButtons.indexOf(e.target) !== -1) {
      const button = e.target;
      const action = button.dataset.qrAction;
      if (action === 'download') {
        const a = document.createElement('a');
        a.download = 'QR-Code.png';
        a.href = qrElement.querySelector('img').src;
        console.log(a.href);
        a.click();
        a.remove();
      } else if (action === 'copy') {
        fetch(qrElement.querySelector('img').src).then(res => res.blob()).then(blob => navigator.clipboard.write([new ClipboardItem({[blob.type]:blob})]));
      } else if (action === 'visit') {
        // handled organically
      }
    }
  }
});
:root {
  --theme-color: #ff0;
  --trace-size: 6%;
  --trace-distance: 5%;
}
html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}
body {
  background-color: var(--theme-color);
}
#qrcode {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%)
}
#qrcode {
  background-color: inherit;
  transition: all 0.15s ease-out;
}
#qrcode::before {
  content: '';
  display: block;
  width: var(--trace-size);
  height: var(--trace-size);
  position: absolute;
  background-color: #f00;
  border-radius: 20%;
  animation: 2s ease-in-out 1s infinite normal both qr-trace;
  transition: inherit;
}
#qrcode img {
  background-color: inherit;
  mix-blend-mode: darken;
  image-rendering: pixelated;
  transition: inherit;
}
#qrcode .qr-action {
  display: block;
  width: 33%;
  height: 33%;
  position: absolute;
  left: 50%;
  top: 50%;
  appearance: none;
  -moz-appearance: none;
  -webkit-appearance: none;
  background-color: transparent;
  border: none;
  border-radius: 50%;
  font-size: 20px;
  z-index: 1;
  transition: inherit;
  cursor: pointer;
  text-decoration: none !important;
  transform-style: preserve-3d;
  box-sizing: border-box;
}
#qrcode .qr-action::before,
#qrcode .qr-action::after {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  border-radius: 50%;
  font-family: 'Font Awesome 5 Pro';
  font-weight: 900;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  box-shadow: 0 10px 20px -10px #000;
  transform-style: preserve-3d;
  transition: all .45s ease-out;
}
#qrcode .qr-action::before {
  backface-visibility: hidden;
  transform: translateZ(0px) scale(1);
  background-color: #fff;
  color: #000;
}
#qrcode .qr-action::after {
  transform: translateZ(-1px) scale(0.95);
  background-color: #000;
  color: var(--theme-color);
}
#qrcode .qr-action[data-qr-action="download"]::before,
#qrcode .qr-action[data-qr-action="download"]::after {
  content: 'f381';
}
#qrcode .qr-action[data-qr-action="copy"]::before,
#qrcode .qr-action[data-qr-action="copy"]::after {
  content: 'f0c5';
}
#qrcode .qr-action[data-qr-action="visit"]::before,
#qrcode .qr-action[data-qr-action="visit"]::after {
  content: 'f0c1';
}
#qrcode .qr-action:nth-child(1) {
  transform: translate(-175%, -50%) scale(0);
}
#qrcode .qr-action:nth-child(2) {
  transform: translate(-50%, -50%) scale(0);
}
#qrcode .qr-action:nth-child(3) {
  transform: translate(75%, -50%) scale(0);
}
#qrcode .qr-action i,
#qrcode .qr-action svg {
  pointer-events: none;
}
#qrcode:hover::before {
  opacity: 0;
}
#qrcode:hover img {
  opacity: 0.5;
}
#qrcode:hover .qr-action {
  opacity: 1;
}
#qrcode:hover .qr-action:nth-child(1) {
  transform: translate(-175%, -50%) scale(1);
}
#qrcode:hover .qr-action:nth-child(2) {
  transform: translate(-50%, -50%) scale(1);
}
#qrcode:hover .qr-action:nth-child(3) {
  transform: translate(75%, -50%) scale(1);
}
#qrcode:hover .qr-action:hover::before {
  transform: translateZ(0px) scale(0.95) rotateY(180deg);
}
#qrcode:hover .qr-action:hover::after {
  transform: translateZ(-1px) scale(1) rotateY(180deg);
}
@keyframes qr-trace {
  0%, 10% {
    left: calc(-1 * (var(--trace-size) + var(--trace-distance)));
    top: calc(-1 * (var(--trace-size) + var(--trace-distance)));
    filter: hue-rotate(0deg);
  } 25%, 35% {
    left: calc(100% + var(--trace-distance));
    top: calc(-1 * (var(--trace-size) + var(--trace-distance)));
  } 50%, 60% {
    left: calc(100% + var(--trace-distance));
    top: calc(100% + var(--trace-distance));
  } 75%, 85% {
    left: calc(-1 * (var(--trace-size) + var(--trace-distance)));
    top: calc(100% + var(--trace-distance));
  } 100% {
    left: calc(-1 * (var(--trace-size) + var(--trace-distance)));
    top: calc(-1 * (var(--trace-size) + var(--trace-distance)));
    filter: hue-rotate(360deg);
  }
}
<script src="https://cdn.jsdelivr.net/gh/davidshimjs/qrcodejs/qrcode.min.js"></script>
<script src="https://kit.fontawesome.com/07afc061fe.js" crossorigin="anonymous"></script>

<div id="qrcode"><button class="qr-action" data-qr-action="download"></button><button class="qr-action" data-qr-action="copy"></button><a class="qr-action" data-qr-action="visit" target="_blank" title="Visit QR Source"></a></div>