QRコードをJavaScriptで作る方法

#はじめに
QRコードを作りたいと思い制作しました。
<a href="https://github.com/jeromeetienne/jquery-qrcode">jquery-qrcode.js</a>というライブラリを使用しました。

#最終形態
![スクリーンショット (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/ceb3c8e5-9cb5-4a09-a950-08908f9e8716.png)
ここまでやってみましょう。

#QRコードを生成するHTMLとJavaScriptを書く

まずは、jquery-qrcode.jsをダウンロードする。

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Make-QR-Code</title>
  </head>
  <body>
    <div class="qr-input">
      <input type="text" name="" value="" id="ip-qrcode" placeholder="Text"><br>
      <div class="option">
        <input type="number" pattern="\d*" onpaste="return false" name="" value="" placeholder="size(px)" id="size">
        <button type="button" id="make">Make</button>
      </div>
    </div>
    <div class="" id="op-qrcode"></div>
    <a class="hidden" id="link"></a>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="jquery.qrcode.min.js" charset="utf-8"></script>
    <script src="qr-code.js" charset="utf-8"></script>
  </body>
</html>
```
１つ目のinputでテキストを入力します。
2つ目のinputでサイズを指定します。

```js:qr-code.js
function canvas() {
  $('canvas').attr('id', 'canvas'); //canvasにidをつける
};

function hidden() {
  $('#op-qrcode').empty(); //#op-qrcodeの子要素削除
};

$('#make').on('click', function(){ //makeボタンが押された場合の処理
  hidden(); //二回目にmakeがクリックされた場合の処理
  var input = $('#ip-qrcode').val(); //テキストを取得
  var size = $('#size').val(); //サイズを取得
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') { //テキストが入力されていなかった場合の処理
    alert('文字を入力してください。\nPlease enter the characters.');
  } else if (size > 0) { //サイズが指定されている場合の処理
    $('#op-qrcode').qrcode({text: text, width: size, height: size});
    canvas();
  } else { //サイズが指定されていない場合の処理
    $('#op-qrcode').qrcode({text: text, width: 1000, height: 1000});
    canvas();
  }
});

```

jquery-qrcode.jsでは```$('#qrcode').qrcode({'qrcode'})``` と書くとQRコードが生成されます。便利です。
```width:1000,height:1000```とすると、1000px × 1000pxで生成してくれます。

#途中経過1

![スクリーンショット (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/d4b6feb5-d467-6de7-ee99-20a183eddfe5.png)
一応生成されましたがデザイン的にNGですよね。何より、生成されたコードがデカすぎます。
ということで、cssを書いていきます。

#cssを書く
main.css と qr-code.cssを書きます。

```css:main.css
body {
  margin: 20px;
  padding: 20px 30px;
}

.hidden {
  display: none;
}

* {
 -webkit-appearance: none;
}

input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{
  -webkit-appearance:none;margin:0
}

input[type=number]{
  -moz-appearance:textfield
}
```

特に重要ではなさそうですが、```input[type=number]::-webkit-inner-spin-button```で横にあるスピンボタン（矢印）を消します。
![スクリーンショット (18).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/26fdce3b-babc-382b-b117-96828b70131b.png)

```css:qr-code.css
input {
  padding: 12px 14.4px;
  font-size: 18px;
  border-radius: 3px;
  border: 1px solid #ddd;
  box-sizing: border-box;
  margin-bottom: 1rem
}

input:focus {
  box-shadow: 0 0 5px 0 rgba(251, 63, 109, 0.75);
  border: 1px solid #fff;
  outline: 0;
}

button {
  background-color: #fff;
  color: #fb3f6d;
  border: 1px solid #fb3f6d;
  padding: 12px 14.4px;
  font-size: 18px;
  border-radius: 3px;
  margin-bottom: 16px;
  width: 88px;
  cursor: pointer;
}

button:hover {
  background-color: #fff5f7;
  transition-duration: 0.2s
}

button:focus {
  background-color: #fff5f7;
  outline: none;
  box-shadow: 0 0 5px 0 rgba(251, 63, 109, 0.75);
}

canvas {
  width: 250px;
  height: 250px;
  margin: 10px;
}

#size {
  width: 120px;
  text-align: center;
}

#size::placeholder {
  text-align: center;
}

input:focus::placeholder {
  visibility: hidden;
}

#make {
  margin-right: 10px;
}

#ip-qrcode {
  width: 100%;
  font-size: 20px
}
```

```html:index.html
<link rel="stylesheet" href="main.css">
<link rel="stylesheet" href="qr-code.css">
```
忘れずにhtmlでcssを指定しましょう。

#途中経過2

![スクリーンショット (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/508e5530-09b7-e557-ef13-84c2351acecf.png)
いい感じですね。
ですが、ダウンロードやサイズを指定するのは面倒くさいのでワンクリックでサイズ指定できるようにしていきましょう。
#UI改善1

```html:index.html
<button class="hidden" type="button" id="down" onclick="download()">Download</button>
<button type="button" name="button" id="500">500px</button>
<button type="button" name="button" id="1000">1000px</button>
<button type="button" name="button" id="1500">1500px</button>
```
```<button type="button" id="make">Make</button>```のあとに突っ込みます。

```css:qr-code.css
#down {
  background-color: #fb3f6d;
  width: 130px;
  color: #fff;
  border: 1px solid #da2652;
  margin-bottom: 1rem;
  cursor: pointer;
}

#down:hover {
  background-color: #fff5f7;
  border: 1px solid #fb3f6d;
  color: #fb3f6d;
  transition-duration: 0.2s
}

#down:focus {
  color: #fb3f6d;
  border: 1px solid #fb3f6d;
  background-color: #fff5f7;
  outline: none;
  box-shadow: 0 0 5px 0 rgba(251, 63, 109, 0.75);
}
```
追加します。

```js:qr-code.js
function canvas() {
  $('canvas').attr('id', 'canvas');
  $('#down').removeClass('hidden') //新しく追加
};

function hidden() {
  $('#op-qrcode').empty();
  $('#down').addClass('hidden') //新しく追加
};

$('#500').on('click', function(){
  hidden();
  var input = $('#ip-qrcode').val();//inputのvalueを取得
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') {
    alert('文字を入力してください。\nPlease enter the characters.');
  } else {
    $('#op-qrcode').qrcode({text:text, width:500, height:500});
    canvas();
  }
});

$('#1000').on('click', function(){
  hidden();
  var input = $('#ip-qrcode').val();//inputのvalueを取得
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') {
    alert('文字を入力してください。\nPlease enter the characters.');
  } else {
    $('#op-qrcode').qrcode({text:text, width:1000, height:1000});
    canvas();
  }
});

$('#1500').on('click', function(){
  hidden();
  var input = $('#ip-qrcode').val();//inputのvalueを取得
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') {
    alert('文字を入力してください。\nPlease enter the characters.');
  } else {
    $('#op-qrcode').qrcode({text:text, width:1500, height:1500});
    canvas();
  }
});

function download() {
  var canvas = document.getElementById('canvas');
  var link = document.getElementById('link');
  link.href = canvas.toDataURL('image/png');
  link.download = 'qrcode.png';
  link.click();
};

```

#途中経過3
![スクリーンショット (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/b1bab19a-dfc4-4371-f3b5-11400caad488.png)
いいですね。
もっと便利にしていきます。

#UI改善2 ショートカット

<a href="http://www.openjs.com/scripts/events/keyboard_shortcuts/">shortcut.js</a>を使います。
ダウンロードをして

```html:index.html
<script src="shortcut.js" charset="utf-8"></script>
```
忘れずに```qr-code.js```の前に突っ込んでください。

```js:qr-code.js
shortcut.add('Ctrl+D',function() {
  download()
}); //Ctrl+Dでダウンロード

shortcut.add('Ctrl+M',function() {
  hidden();
  var input = $('#ip-qrcode').val();//inputのvalueを取得
  var size = $('#size').val();
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') {
    alert('文字を入力してください。\nPlease enter the characters.');
  } else if (size > 0) {
    $('#op-qrcode').qrcode({text: text, width: size, height: size});
    canvas();
  } else {
    $('#op-qrcode').qrcode({text: text});
    canvas();
  }
}); //Ctrl+Mで生成

shortcut.add('Ctrl+Shift+C',function() {
  hidden()
}); //Ctrl+Shift+Cでクリア 隠しコマンド

```
shortcut.jsは```shortcut.add('Ctrl+Enter',function() {処理})```とすると簡単にショートカットを作れる。

```html:index.html
<button type="button" id="make" title="Ctrl+M">Make</button>
<button class="hidden" type="button" id="down" onclick="download()" title="Ctrl+D">Download</button>
```

コマンドを認知しやすいようにtitleを追加します。

#完成
![スクリーンショット (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/ceb3c8e5-9cb5-4a09-a950-08908f9e8716.png)

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Make-QR-Code</title>
    <link rel="stylesheet" href="main.css">
    <link rel="stylesheet" href="qr-code.css">
  </head>
  <body>
    <div class="qr-input">
      <input type="text" name="" value="" id="ip-qrcode" placeholder="Text"><br>
      <div class="option">
        <input type="number" pattern="\d*" onpaste="return false" name="" value="" placeholder="size(px)" id="size">
        <button type="button" id="make" title="Ctrl+M">Make</button>
        <button class="hidden" type="button" id="down" onclick="download()" title="Ctrl+D">Download</button>
        <button type="button" name="button" id="500">500px</button>
        <button type="button" name="button" id="1000">1000px</button>
        <button type="button" name="button" id="1500">1500px</button>
      </div>
    </div>
    <div class="" id="op-qrcode"></div>
    <a class="hidden" id="link"></a>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="jquery.qrcode.min.js" charset="utf-8"></script>
    <script src="shortcut.js" charset="utf-8"></script>
    <script src="qr-code.js" charset="utf-8"></script>
  </body>
</html>
```

```js:qr-code.js
function canvas() {
  $('canvas').attr('id', 'canvas'); //canvasにidをつける
  $('#down').removeClass('hidden')
};

function hidden() {
  $('#op-qrcode').empty(); //#op-qrcodeの子要素削除
  $('#down').addClass('hidden')
};

$('#make').on('click', function(){ //makeボタンが押された場合の処理
  hidden(); //二回目にmakeがクリックされた場合の処理
  var input = $('#ip-qrcode').val(); //テキストを取得
  var size = $('#size').val(); //サイズを取得
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') { //テキストが入力されていなかった場合の処理
    alert('文字を入力してください。\nPlease enter the characters.');
  } else if (size > 0) { //サイズが指定されている場合の処理
    $('#op-qrcode').qrcode({text: text, width: size, height: size});
    canvas();
  } else { //サイズが指定されていない場合の処理
    $('#op-qrcode').qrcode({text: text, width: 1000, height: 1000});
    canvas();
  }
});

$('#500').on('click', function(){
  hidden();
  var input = $('#ip-qrcode').val();//inputのvalueを取得
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') {
    alert('文字を入力してください。\nPlease enter the characters.');
  } else {
    $('#op-qrcode').qrcode({text:text, width:500, height:500});
    canvas();
  }
});

$('#1000').on('click', function(){
  hidden();
  var input = $('#ip-qrcode').val();//inputのvalueを取得
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') {
    alert('文字を入力してください。\nPlease enter the characters.');
  } else {
    $('#op-qrcode').qrcode({text:text, width:1000, height:1000});
    canvas();
  }
});

$('#1500').on('click', function(){
  hidden();
  var input = $('#ip-qrcode').val();//inputのvalueを取得
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') {
    alert('文字を入力してください。\nPlease enter the characters.');
  } else {
    $('#op-qrcode').qrcode({text:text, width:1500, height:1500});
    canvas();
  }
});

function download() {
  var canvas = document.getElementById('canvas');
  var link = document.getElementById('link');
  link.href = canvas.toDataURL('image/png');
  link.download = 'qrcode.png';
  link.click();
};

shortcut.add('Ctrl+D',function() {
  download()
}); //Ctrl+Dでダウンロード

shortcut.add('Ctrl+M',function() {
  hidden();
  var input = $('#ip-qrcode').val();//inputのvalueを取得
  var size = $('#size').val();
  var text = unescape(encodeURIComponent(input));//日本語対応
  if (input == '') {
    alert('文字を入力してください。\nPlease enter the characters.');
  } else if (size > 0) {
    $('#op-qrcode').qrcode({text: text, width: size, height: size});
    canvas();
  } else {
    $('#op-qrcode').qrcode({text: text});
    canvas();
  }
}); //Ctrl+Mで生成

shortcut.add('Ctrl+Shift+C',function() {
  hidden()
}); //Ctrl+Shift+Cでクリア 隠しコマンド
```

```css:main.css
body {
  margin: 20px;
  padding: 20px 30px;
}

.hidden {
  display: none;
}

* {
 -webkit-appearance: none;
}

input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{
  -webkit-appearance:none;margin:0
}

input[type=number]{
  -moz-appearance:textfield
}
```

```js:qr-code.css
input {
  padding: 12px 14.4px;
  font-size: 18px;
  border-radius: 3px;
  border: 1px solid #ddd;
  box-sizing: border-box;
  margin-bottom: 1rem
}

input:focus {
  box-shadow: 0 0 5px 0 rgba(251, 63, 109, 0.75);
  border: 1px solid #fff;
  outline: 0;
}

button {
  background-color: #fff;
  color: #fb3f6d;
  border: 1px solid #fb3f6d;
  padding: 12px 14.4px;
  font-size: 18px;
  border-radius: 3px;
  margin-bottom: 16px;
  width: 88px;
  cursor: pointer;
}

button:hover {
  background-color: #fff5f7;
  transition-duration: 0.2s
}

button:focus {
  background-color: #fff5f7;
  outline: none;
  box-shadow: 0 0 5px 0 rgba(251, 63, 109, 0.75);
}

canvas {
  width: 250px;
  height: 250px;
  margin: 10px;
}

#size {
  width: 120px;
  text-align: center;
}

#size::placeholder {
  text-align: center;
}

input:focus::placeholder {
  visibility: hidden;
}

#make {
  margin-right: 10px;
}

#ip-qrcode {
  width: 100%;
  font-size: 20px
}

#down {
  background-color: #fb3f6d;
  width: 130px;
  color: #fff;
  border: 1px solid #da2652;
  margin-bottom: 1rem;
  cursor: pointer;
}

#down:hover {
  background-color: #fff5f7;
  border: 1px solid #fb3f6d;
  color: #fb3f6d;
  transition-duration: 0.2s
}

#down:focus {
  color: #fb3f6d;
  border: 1px solid #fb3f6d;
  background-color: #fff5f7;
  outline: none;
  box-shadow: 0 0 5px 0 rgba(251, 63, 109, 0.75);
}
```

#まとめ
jquery-qrcode.jsを用いれば簡単に作れることが分かりました。
個人的に使いやすいUIにすることができたと思います。

ソース↓
https://github.com/risuney/qr-code