はじめに
構成
- 環境構築: https://qiita.com/rayan/items/5d04ee2ca7860c220dec
- ログインページ: https://qiita.com/rayan/items/1f0576395b9727635461
- メニュー: https://qiita.com/rayan/items/3645506cdb10512fd87c
- ユーザー設定確認・変更ページ: https://qiita.com/rayan/items/824f8b4c29384ae96258
- アイテム登録ページ: 今回
GitHubリポジトリ
準備中
省略名称
RTDB: Realtime Database
操作するファイル
- public
- index.html
- src
- router
- index.js
- mixins
- DatabaseOps.js
- views
- ItemRegisteration.vue
- router
新しく用いるライブラリ
- 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コードの上に説明する文字を配置する。
- アイテムIDからリンクを作成
- 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コードが生成されることを確認する。
次回
アイテム一覧ページ