この記事は「PWA Advent Calendar 2019」の18日目の記事です。
今年の春、Progressive Web Apps や Firebase の練習がてら、英単語学習ソフトを開発しました。
(が、そのまま放置していた)
作りっぱなしももったいないので、アドベントカレンダーに乗じてご紹介します。
以下のような特徴があります。
- Vue.js を利用したMPA(Multi-page Application)
- Progressive Web Apps 対応。Windows10/スマホにインストールして、オフラインで動作。
- 英単語の発音をクリックして確認できる (Web Speech API 利用)
- Firebase のHosting機能を利用して公開
- 選択肢と回答をランダムに生成。英単語アプリにありがちな「同じ選択肢と回答が繰り返され、出題パターンを覚えてしまう」ことがないようにした。(800の4乗x10問で、組み合わせは4兆通りぐらい?)
開発中のメモをもとに、いくつか備忘録を記述します。
Web Speech API による英語音声の確認
アプリを起動すると、英単語と4つの選択肢が表示されます。英単語をクリック・タップすると、英語の発音を確認できます。
Speech Synthesis API という、Web Speech APIの音声合成機能を利用しました。
pronounce: function () {
// confirm English word's pronounciation
let u = new SpeechSynthesisUtterance();
u.lang = 'en-US';
u.text = document.getElementById('englishWord').innerHTML;
u.volume = "1";
speechSynthesis.speak(u);
}
※Speech Synthesis API の使い方については拙稿「Web Speech API を 利用して 英単語の音声確認をするアプリを作る」にまとめました。
Service Worker によるデータキャッシュ
html・CSS・効果音などのアセットファイル類を、Service Worker でまとめてキャッシュしています。
バージョンをキャッシュのキーとして登録。バージョン情報に更新があった場合、キャッシュパージ後、ファイルをキャッシュしなおすようにしました。
const CACHE_NAME = `BasicEnglish800-${version}`;
---- 中略 ----
// Service Worker へファイルをインストール
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function (cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
// リクエストされたファイルが Service Worker にキャッシュされている場合
// キャッシュからレスポンスを返す
self.addEventListener('fetch', function (event) {
if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin')
return;
event.respondWith(
caches.match(event.request)
.then(function (response) {
if (response) {
return response;
}
return fetch(event.request);
}
)
);
});
// Cache Storage にキャッシュされているサービスワーカーのkeyに変更があった場合
// 新バージョンをインストール後、旧バージョンのキャッシュを削除する
// (このファイルでは CACHE_NAME をkeyの値とみなし、変更を検知している)
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(keys => Promise.all(
keys.map(key => {
if (!CACHE_NAME.includes(key)) {
return caches.delete(key);
}
})
)).then(() => {
console.log(CACHE_NAME + "activated");
})
);
});
※Service Workerの使い方や詳細については拙稿「Progressive Web Apps (PWA) 学習者のメモ その1 (Service Worker)」にまとめました。
Vue.js で問題を生成、回答記録を追跡
Vue.js を利用して、回答数を記録。
最初に10問分の英単語・選択肢・回答を、ランダムに生成。
配列に単語・回答・選択肢のデータを格納。
問題を解いて「次へ」をクリック・タップすることで、配列を切り替え、次の問題を表示。
1問解くたびに、次の問題へ切り替え。
10問終了後に正誤のデータを確認し、回答を記録するようにしました。
const vm = new Vue({
el: '#el',
data() {
return {
arr: answerList,
count: 0,
choice: quizList,
result: [],
}
},
methods: {
check: function (event) {
// check user's answer each by each
let target = document.getElementById("answerOptions");
target.setAttribute('style', 'pointer-events: none;');
let rightAnswer = this.arr[this.count].Japanese;
let chosenAnswer = event.target.innerHTML;
if (rightAnswer === chosenAnswer) {
correctSound.play();
message.innerHTML = "正解!";
addAnswer("○");
} else {
wrongSound.play();
message.innerHTML = "残念!";
addAnswer("×");
}
this.count === 9 ? complete() : unComplete();
},
※Vue.js を利用した回答の切り替え(=配列の切り替え)については、拙稿「Vue.js で 配列とJSONの切り替え表示を行う」にまとめました。
振り返り
一つ一つは単純なコードですが、組み合わせることで、それなりにアプリとして形になった気がしました。
できれば
- Firebase のユーザー認証を利用して、リアルタイムDBに回答記録を保存
- 全アプリユーザーの間で、どの単語の誤答率が高いか、統計を取る
までやってみたかったのですが、時間切れで実装できず。
Firebaseの利用はHostingのみとなりました。
そのうち時間を作ってチャレンジしてみたいと思います。
備考
以下のサイトのデータ・情報を元に開発しました。
- 英単語データ
*
「800ベーシック英単語」 - ランダムな配列生成ロジック