0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

QR忘れ物アプリ (5) アイテム登録ページ [Vue,Vuetify,Firebase]

Last updated at Posted at 2021-04-22

はじめに

構成

  1. 環境構築: https://qiita.com/rayan/items/5d04ee2ca7860c220dec
  2. ログインページ: https://qiita.com/rayan/items/1f0576395b9727635461
  3. メニュー: https://qiita.com/rayan/items/3645506cdb10512fd87c
  4. ユーザー設定確認・変更ページ: https://qiita.com/rayan/items/824f8b4c29384ae96258
  5. アイテム登録ページ: 今回

GitHubリポジトリ

準備中

省略名称

RTDB: Realtime Database

操作するファイル

  • public
    • index.html
  • src
    • router
      • index.js
    • mixins
      • DatabaseOps.js
    • views
      • ItemRegisteration.vue

新しく用いるライブラリ

  • qrcodejs: QRコードをCanvas上に描画する。
  • html2canvas: div要素で表示されている内容をCanvas上に描画する。

public/index.html

新しく用いる二つのライブラリを追加する。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <!-- update the version number as needed -->
    <script src="/__/firebase/8.3.1/firebase-app.js"></script>
    <!-- include only the Firebase features as you need -->
    <script src="/__/firebase/8.3.1/firebase-auth.js"></script>
    <script src="/__/firebase/8.3.1/firebase-database.js"></script>
    <script src="/__/firebase/8.3.1/firebase-functions.js"></script>
    <!-- 
      initialize the SDK after all desired features are loaded, set useEmulator to false
      to avoid connecting the SDK to running emulators.
    -->
    <script src="/__/firebase/init.js?useEmulator=true"></script>
    <script src="https://www.gstatic.com/firebasejs/ui/4.8.0/firebase-ui-auth.js"></script>
    <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.8.0/firebase-ui-auth.css" />
    <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
    <script defer src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.js"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/html2canvas@1.0.0-rc.5/dist/html2canvas.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

src/views/ItemRegisteration.vue

アイテム登録ページの要素。

  • まず、アイテム名を設定する。
  • var itemId = this.pushItems(item)でRTDBにアイテムをpushし、その時のkeyをitemIdに格納
  • qrcodeDiv
    • アイテムIDからリンクを作成
      • var url = 'http://127.0.0.1:5000/?foundItemId='+itemId
    • qrcodejsでリンクをQRコードに変換
    • QRコードの上に説明する文字を配置する。
  • qrcodeImage
    • qrcodeDivを表示する
    • html2canvasでqrcodeDivの内容のスクリーンショットを取り、描画する。
    • これにより、qrcodeImageで右クリックすることで文字を含んだQRコードをブラウザ上で保存することができる。
    • qrcodeDivが表示されたままだと、QRコードが二つ表示されてしまうのでqrcodeDivを非表示にする、
<template>
  <div>
    <Header :title="title"/>
    <v-card class="overflow-hidden">
      <v-sheet>
        <v-list-item-group
          v-model="selectedItem"
          color="primary"
        >
          <v-list-item
            v-for="(preference, i) in preferences"
            :key="i"
          >
            <v-text-field
              v-if="preference.type == 'textField'"
              v-model="preference.value"
              :label="preference.text"
            ></v-text-field>
            <v-checkbox
              v-if="preference.type == 'checkbox'"
              v-model="preference.value"
              :label="preference.text"
            ></v-checkbox>
            <v-select
              v-if="preference.type == 'select'"
              v-model="preference.value"
              :items="preference.values"
              :label="preference.text"
            ></v-select>
          </v-list-item>
        </v-list-item-group> 
        <v-spacer/>
        <v-list-item>
          <v-btn
            class="mr-4"
            @click="createQR"
          >
            Submit
          </v-btn>         
        </v-list-item>
        <v-spacer/>
        <v-list-item>     
          <div id="qrcodeImage"></div>
        </v-list-item>
      </v-sheet>
    </v-card>
    <div id="qrcodeDiv" class="container" style="margin: 0px; display: none;">
      <span class="qrcodeText" style="font-weight: bold">"QR Lost and Found" [QRコード忘れ物タグ]</span>
      <span class="qrcodeText">Please contact owner using QR code below</span>
      <span class="qrcodeText">拾った方はQRコードで所有者へ連絡をお願い致します</span>
      <span class="qrcodeText" id="qrcodeItemName"></span>
      <div id="qrcode" style="margin-top: 4px;"></div>
    </div>
  </div>
</template>

<style lang="scss">
.qrcodeText {
  line-height: 13px;
  font-size: 10px;
  display: block;
}
.container {
  background-color: #ffffff;
  border-radius: 2px;
  border-style: solid;
  border-color: #000000;
  width: 270px;
  text-align: center;
}
</style>

<script>
import Header from '@/components/Header'
import DatabaseOps from '@/mixins/DatabaseOps'

export default {
  name: "ItemRegisteration",
  data: () => ({
    preferences: [
      { text: 'Name of Item', value: '', type: 'textField'}
    ],
    title: 'Item Registeration'
  }),
  components: {
    Header
  },
  methods: {
    createQR() {
      var itemName = this.preferences[0].value;
      var item = {
        'currentLocation': '',
        'foundLocation': '',
        'found': false,
        'lost': false,
        'name': itemName
      }
      var itemId = this.pushItems(item);
      this.setItemIds(itemId);
      var url = 'http://127.0.0.1:5000/?foundItemId='+itemId;
      var qrcodeImageElementId = 'qrcodeImage';
      document.getElementById(qrcodeImageElementId).innerHTML = ''; // delete the previous QR code images
      this.generateQrcode(url, itemName);
      this.divToImage(qrcodeImageElementId);
    },
    generateQrcode(url, qrcodeItemName) {
      var qrcodeItemNameElementId = 'qrcodeItemName';
      var qrcodeElementId = 'qrcode';
      document.getElementById(qrcodeItemNameElementId).innerHTML = 'Item identifier: '+qrcodeItemName;
      document.getElementById(qrcodeElementId).innerHTML = ''; // reset qr code
      new QRCode(document.getElementById(qrcodeElementId), {
        text: url,
        width: 256,
        height: 256,
        colorDark : "#000000",
        colorLight : "#ffffff",
        correctLevel : QRCode.CorrectLevel.H
      });
    },
    divToImage(qrcodeImageElementId) {
      var qrcodeDivElementId = 'qrcodeDiv';
      document.getElementById(qrcodeDivElementId).style.display = 'block'; // show the div for converting to image
      html2canvas(document.getElementById(qrcodeDivElementId)).then((canvas) => { // convert div(QR code + text) into image
        document.getElementById(qrcodeImageElementId).appendChild(canvas);
        document.getElementById(qrcodeDivElementId).style.display = 'none'; // hide the original div
      });
    }
  },
  mixins: [DatabaseOps]
};
</script>

router/index.js

新しくつくったItemRegisterationページの情報を追加する。

import Vue from "vue";
import VueRouter from "vue-router";

Vue.use(VueRouter);

const routes = [
  {
    path: "*",
    redirect: "/"
  },
  {
    path: "/mainMenu",
    name: "MainMenu",
    meta: { requiresAuth: true },
    component: () =>
      import("@/views/MainMenu.vue"),
  },
  {
    path: "/userPreferences",
    name: "UserPreferences",
    meta: { requiresAuth: true },
    component: () =>
      import("@/views/UserPreferences.vue"),
  },
  {
    path: "/itemRegisteration",
    name: "ItemRegisteration",
    meta: { requiresAuth: true },
    component: () =>
      import("@/views/ItemRegisteration.vue"),
  },
  {
    path: "/",
    name: "Authentication",
    component: () =>
      import("@/views/Authentication.vue"),
  },
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes,
});

router.beforeEach((to, from, next) => {
  let requiresAuth = to.matched.some(record => record.meta.requiresAuth)
  let currentUser = firebase.auth().currentUser
  if (requiresAuth) { // if this page requires auth, redirect to auth page
    if (!currentUser) {
      next({
        path: '/',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // this is required
  }
})

export default router;

Build

  • ビルドし、動作をテストする。動作のテストにはFirebase Emulatorが必要であるため、起動する。
npm run build
firebase emulators:start
  • dist/index.htmlをブラウザで閲覧する。ログイン後、ItemRegisterationページに移動する。
  • アイテム名を設定し、submitを押す。説明付きのQRコードが生成されることを確認する。

次回

アイテム一覧ページ

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?