JavaScriptを使ってQRコード生成ができるサイトを作成してみた【React】

JavaScript

これまで大学の講義等でCやPythonのプログラムは頻繁に書いてきましたが、Web系のプログラミングは未経験でした。世の中の大半のサービスはWeb上で動くものなので、将来エンジニアになる可能性が高い自分にとって避けては通れない道です。そこで今回はJavaScriptの”React”というフレームワーク(?ライブラリ?)を使用した簡単なサイトの作成に取り組みました。

今回作成したサイト

QRコードを生成してくれるサイトを作りました。サイトのデザインは以下のものを参考にしました。

Generate QR Code in JQuery | JSON World
A demo to create qr code with jquery

サイトの動作を説明します。まず起動直後の画面はこうなります。

タイトルの”QRコード生成”の文字、”QRコード化したい文字列を入力”の文字、テキストエリア、サイズ指定の選択、「表示」ボタン、「保存」ボタンがあります。

テキストエリアにテキストを入れて「表示」ボタンを押すと以下のような画面になります。

QRコードが表示されています。サイズのタブから値を変更すると、QRコードのサイズも変わります。ここで、「保存」ボタンを押すと以下のようになります。

QRコードのファイルがダウンロードされていることが分かります。

ソースコード全体は以下のgithubにアップロードしています。

GitHub - MARBAS0610/react_qr_generator: JavaScriptのReactフレームワークでQRコード生成サイトを作りました。
JavaScriptのReactフレームワークでQRコード生成サイトを作りました。. Contribute to MARBAS0610/react_qr_generator development by creating an account on GitHub.

また、作成したサイトは以下のリンクで公開しています。

QRコード生成

Reactのインストール、基本操作

ReactはJavaScriptでフロントエンド(ユーザーの見える部分)のプログラミングを行う際のフレームワークです。これを使うことで、入力が変化したときのリアルタイムの処理などを効率よく実装することができます。環境設定については、以下のサイトを参考にするとよいでしょう。環境設定に関する基本的な情報が載っています。

Reactの基礎【環境構築編】

また、Reactの基本について学べるMicrosoftの公式サイトはこちらになります。jsx、コンポーネント等Reactを使いこなすうえで必須となる知識が学べます。ぜひ一度コードに目を通してみてください。

React の概要 - Training
最新の Web 開発では、通常、既存のフレームワークが使用されます。 ここでは、ブラウザーベースのアプリケーションを作成するのに React がどのように役立つのかを調べます。 開発者がフレームワークを使用するために必要な主要なスキルについて学習します。

ファイルの構造

npmのコマンド”create-react-app”を実行すると自動的にディレクトリと必要なファイルを構成してくれます。その中で、今回編集するのは以下の4つだけです。

  • index.html

publicフォルダにある、webページの本体となるコード。

  • App.jsx

srcフォルダにある。デフォルトではApp.jsとなっているはずなので拡張子を変更しておく。HTMLのコードに変換されるJavaScriptのコンポーネントを書く。

  • index.jsx

srcフォルダにある。実際にページを描画する処理を担当する。

  • index.css

srcフォルダ直下に新しく作成する(もともとあるApp.cssに書き足してもOKです)。webページのスタイル(テキストの配置、色等)を指定するコード。

次は、それぞれのコードについて説明していきます。

HTMLのコード

HTMLのコードは以下のようになります。bodyの部分はほぼすべてJavaScriptで作るのでこれで全部です。

<!DOCTYPE html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>QRコード生成</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/dist/index.js"></script>
  </body>
</html>

1行目と11行目のhtmlタグ(タグは<タグ名>の形で表される)はHTMLにおける決まり文句のようなものです。

2~6行目のheadタグは、ヘッダを示します。webページの設定をここに記述します。3行目は文字コード、4行目はページの幅をデバイスの幅に合わせる、5行目はページタイトル(画面上部のタブに表示されるやつ)です。

7~10行目のbodyタグは、実際にページに表示される部分です。App.jsxとindex.jsxを利用してこの部分のコードを生成します。

CSSのコード

CSSのコードは、

要素名{
  スタイルの情報1;
  スタイルの情報2;
  ...
}

もしくは

.クラス名{
  スタイルの情報1;
  スタイルの情報2;
  ...
}

のように書きます。HTMLの要素名でないオリジナルのスタイルはクラス名の前に”.”を付けます。

今回のプログラムのうち、divタグの中の要素を中央にそろえるcentering_blockクラスとHTMLで文字入力のエリアの要素であるtextareaのスタイルを決めるコードを以下に抜粋します。

.centering_block{
  padding: 10px;
  text-align: center;
  background-color: #fff;
  height: auto;
}

textarea{
  width: 30%;
  height: 80px;
  margin:20px;
}

centering_blockの方は、上から順に余白、テキストを中央揃えにする、背景色の設定、高さの設定です。高さがautoになっていると、そのブロックの内容をきれいに並べられるくらいの高さをプログラムが自動で決定してくれます。

textareaの方は、幅と高さと余白を設定しているだけです。幅の30%はページ全体の幅に対して30%という意味です。高さは80ピクセル、余白は20ピクセルに設定しました。

index.cssの全文は以下のようになりました。

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

/* ブロック要素の中央揃え */
.centering_block{
  padding: 10px;
  text-align: center;
  background-color: #fff;
  height: auto;
}

/* 背景色を変える */
.centering_block_gray{
  margin-right: 5%;
  margin-left: 5%;
  padding: 10px;
  text-align: center;
  background-color: #888;
  height: auto;
}

/* インライン要素(p等)の中央揃え */
.centering_inline{
  margin: 0 auto;
  background-color: #fff;
}

/* テキストエリア */
textarea{
  width: 30%;
  height: 80px;
  margin:20px;
}

button{
  margin: 20px;
}

JavaScript(React)のコード

App.jsx

App()のコード

いよいよ本題のApp.jsxに入ります。これが今回のサイトの本体、HTMLのbody内部を記述するコードになります。

App.jsの本体は以下のように記述します。

function App() {
    return(
        本体のHTMLコード
    );
}

export default App;

return()の内部にHTMLのコードを書きます。例えば、サイトの上部にタイトル”QRコード生成”を記述する場合、App()は以下のようになります。

function App() {
    return (
        <div>
          <div class="centering_block">
            <h1 class="centering_inline">QRコード生成</h1>
          </div>
        </div>
    );
}

タイトルを表示する部分をdivタグで囲い、index.cssで指定したcentering_blockクラスとcentering_inlineクラスを利用しました。

関数コンポーネントの定義

Reactの特徴の一つに関数コンポーネントの利用があります。関数コンポーネントとは、直感的に言うと、関数と同様の働きをする変数です。記述方法は以下のようになります。

const 関数名 = (引数) => {
    関数の内容
}

このプログラムで使用する関数コンポーネントは以下のものがあります。

  • download(): 生成されたQRコードをダウンロードする。
  • printText(): テキストエリアに入力されたテキストと、選択されたQRコードのサイズをQRコードに反映する。「表示」ボタンが押されたとき呼ばれる。
  • Export(): QRコードを画像に変換しそのパスを得て、download()を呼び出してダウンロードする。

変数とuseState()

アプリの内部では、ユーザーの操作を通して値を変えたい変数があると思います。例えば、QRコードのサイズをユーザーが選択すると、それに応じてQRコードのサイズが変わるなどがあるでしょう。このような目的で使用されるのがuseState()です。useState()は以下のように定義します。

const [変数名, 値を更新する関数名] = useState(変数の初期値)

変数名とその変数の値を更新する関数名をセットで宣言します。この変数の値をHTMLのコードで使用する際は変数名を{}で囲みます。変数の値の更新は、HTMLのコンポーネントのコールバック関数(buttonタグのonClick()等)として使用します。

QRコードの表示方法

QRコードの表示のため、react-qr-codeというライブラリを使用しました。以下のgithubに利用方法が書いてあります。英語で書かれていますが、基本的に例のコードをそのまま使えば問題ないです。

GitHub - rosskhanas/react-qr-code: A QR code generator for React and React Native.
A QR code generator for React and React Native. Contribute to rosskhanas/react-qr-code development by creating an account on GitHub.

ダウンロードの実装

QRコードを表示するために、html2canvasというライブラリを使用しました。これを使うと、ページの一部をcanvasに変換できます。この機能をExport()で実装しました。

さらにこのcanvasを画像としてダウンロードする機能をdownload()で実装しました。このコードは以下のサイトのものをほぼそのまま利用させてもらいました。

React Component を画像に変換してダウンロードさせる | Simple is Best
特定の Component を画像に変換してダウンロードする機能を実装したかったので探しました。( というライブラリを用いることで可能になります。## ライブラリをインストールnpm 派は```shellnpm i html2canvas```Yarn 派は```shellyarn

App.jsxのコードの全文は以下のようになります。ここまで説明していないタグや関数もありますが、調べればすぐ情報が得られると思います。

import React, { useState } from 'react';
import './index.css';
import QRCode from "react-qr-code";
import html2canvas from 'html2canvas';

const download = (uri) => {
  const downloadLink = document.createElement("a");
  if (typeof downloadLink.download === "string") {
    downloadLink.href = uri;
    downloadLink.download = "qrcode.png";
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
  }else{
    window.open(uri);
  }
}

const Export = () => {
  const target = document.getElementById("qrcode");
  html2canvas(target).then(canvas => {
    const targetImgUri = canvas.toDataURL("img/png");
    download(targetImgUri);
})};

function App() {
  // アプリ本体
  // usestate:変数とその値を更新する関数名のセット
  // textという変数とtextの値を更新するsetText()メソッドがあるよという意味
  const [text, setText] = useState("");
  const [inputText, setInputElement] = useState("");
  const [size, setSize] = useState("200px");
  const [sizeval, setSizeval] = useState("200px");

  // テキストの表示(関数コンポーネント)
  const printText = () => {
    if(inputText !== "") {
      setText(inputText);
      setSize(sizeval);
      // console.log(size);
    }
    else
    {
      setText("");
    }
  }

  return (
    <div>
      <div class="centering_block">
        <h1 class="centering_inline">QRコード生成</h1>
      </div>

      <div class="centering_block">
        <p class="centering_inline">
          QRコード化したい文字列を入力してください。
        </p>
      </div>

      <div class="centering_block_gray">
        {/* textarea: テキストボックス(複数行) */}
        <textarea value={inputText} onChange={(e) => setInputElement(e.target.value)} type="text" placeholder="入力してボタンを押してください。" />
      </div>
      
      {/* サイズ選択、ボタン */}
      <div class="centering_block">
        サイズ:
        <select onChange={(e) => setSizeval(e.target.value)}>
          <option value="100px">100×100</option>
          <option value="200px" selected>200×200(デフォルト)</option>
          <option value="300px">300×300</option>
        </select>

        <button onClick={printText}>表示</button>
      </div>

      {/* QRコード表示 */}
      <div class="centering_block" id='qrcode'>
        {/* textの長さが>0ならQR表示。&&使う。 */}
        {(text.length > 0) && (
        <QRCode
          // size={256}
          style={{ height: size, width: size }}
          value={text}
          viewBox={`0 0 256 256`}
        />
        )}
      </div>

      <div class="centering_block">
        {text} <br />
      </div>

      <div class="centering_block">
        <button onClick={() => Export()}>表示</button>
      </div>

    </div>
  );

}

export default App;

index.jsx

index.jsxは非常に短いので先にコード全文を示します。

import React from "react";
import ReactDOM from "react-dom";
import App from './App';

ReactDOM.render(
    <App />,
    document.getElementById('app')
);

5行目のrender()で実際にwebサイトを描画します。6行目はApp.jsxのApp()で生成されるHTML、7行目は実際にindex.htmlにApp()のHTMLを渡すために使用します。

ビルド

プログラムが完成したら、それを実際にアップする前に「ビルド」という操作が必要になります。ビルドを行うことで初めてインターネット上で表示できるようになります。ビルドの際もひと悶着あったので残しておきます。package.jsonを編集して、

{
  "name": "qr_generator",
  "version": "0.1.0",
  "homepage": "./",
  "private": true,

“homepage”の行を追加する必要がありました。こちらのサイトなどが参考になります。

npm run buildしたReactアプリが真っ白になり何も表示されない原因と解決法 | プログラマーになった 「中卒」 男のブログ

その後npm run buildでできたファイルをサーバーにアップして公開は完了です。

まとめ

今回は、ReactでJavaScriptプログラミングの入門として、QRコードを生成するサイトを作りました。JavaScriptでのプログラミングは初めてでしたので、いろいろ苦戦したポイントはありましたが、JavaScriptは比較的扱いやすいプログラミング言語だと思いました。コーディングの結果がすぐサイト上に反映されるので、プログラミング初心者でも大丈夫だと思います。

自分が特に苦戦したのはuseState()の使い方とダウンロードの実装でした。この辺りは参考URLのコードをほぼそのまま使用したのでまだ理解が不十分なままでした。

次はJavaScriptを使ってブラウザ上で動作するゲームなんかを作ってみたいと思いました。また気が向いたら記事にします。

タイトルとURLをコピーしました