20210906のvue.jsに関する記事は3件です。

Vue.js でタイピング練習ウェブアプリを作ってみた

Vue.jsで、多言語タイピング練習ウェブアプリを作成しました。 URL: https://www.typing-up.pro/ この記事では、主に技術的なところでポイントとなる部分を、備忘録的に解説していきます。githubでコードを公開しているので、細かいところは省き、ポイントのみの解説です。 対象は、Vue.jsの基礎をある程度知っている方です。 プログラミングの練習課題として、タイピング練習ソフトを作ることは定番かと思います。あくまで解法の一つですが、どうぞ参考にしてください。 Githubリポジトリはこちら ※ソースコードは、ローカル環境での個人利用に限り改変自由です。 仕様の概要 このアプリの特徴は、主に次の2つです。 オリジナル問題の利用: 自分で作った問題集をアップロードして、タイピング練習をすることができます。ユーザー登録は必要ありません。 多言語対応: アルファベット入力をする言語であれば、おおよそどの言語でも対応しています。自然言語だけでなく、プログラミング言語なども対応しています。日本語のように変換が必要だったり、複雑な入力体系を持つ言語は対応していません。 使い方の詳細は、ブログ記事をご覧ください。 【オリジナル問題が使える!】多言語タイピング練習アプリを公開しました タイピング正誤判定のロジック まずタイピングソフトの肝となる、キーの正誤判定のロジックです。 大まかに、次の3ステップで正誤判定をしています。 data で問題文、入力されたテキストを定義する 問題文の文字を1文字ずつ分解し配列に変換 入力された文字と問題文の配列の中身を比較し、一致していれば正、不一致であれば誤とする 1.data 定義 data () { return { question: 'This is test', //問題文。サンプルテキストを入れています typed: '', //入力された文字 mistyped: '', //ミスタイプならこちらへ表示 charnum: 0, //正答入力された文字数をカウント wordtoArray: "", //問題文を1文字ずつ分解した配列を格納 } }, 2.問題文の分解 wordtoArrayに、問題文を1文字ずつバラバラにして格納します。  this.wordtoArray = this.question.split(''); 3.問題文と入力文字の比較 キー入力は、mountedのイベントリスナで監視しています。v-modelでtexareaへの入力を監視する方法もあります。 mounted: function() { document.addEventListener('keypress', this.onKeyDown); } methodsのonKeydownで正誤判定をしています。charnumでいま何文字目まで入力しているか把握しています。wordtoArrayのn文字目と比較するというロジックです。 onKeyDown: function(e) { //正しい入力の時 if(this.wordtoArray[this.charnum] == e.key){ this.typed += e.key; //入力された文字列 this.charnum += 1; //現在n文字目 //間違えた時 } else { this.mistyped = e.key; } } あとはHTMLを設定すれば、基本の仕組みは完成です。 <p>{{question}}<p> <textarea placeholder="type here" autofocus readonly>{{typed}}</textarea> <p>{{mistyped}}<p> 問題文の読み込み 基本的な正誤判定ができたら、次は問題文を読み込む仕組みを作ります。 問題文はコードに直接記載するのではなく、外部ファイルから読み込むようにしました。 ステップとしてはおおよそ次の通りです。 assetまたはstaticフォルダにcsvファイルを設置 csvファイルをfetchで読み込み 最大問題数までランダムで取得しdataへ 2のステップからコードを載せます。 2.csvファイルをfetchで読み込み 筆者はwebpackを使いましたが、外部ファイル設置はassetでは上手くいかず、staticに設置しました。 fetch('/static/english.csv') .then(res => res.text()) .then(data => (this.questions_all = this.convertCsvStringToArray(data))) } 参考:Vue.js で CSV ファイルの読み込み methodsのconvertCsvStringToArray問題文を抽出します。 convertCsvStringToArray(str) { str = str.replace( /[^\u0000-\u1FFF]+/g, ''); //unicodeの範囲を指定。範囲外の文字を削除 str = str.split("\n").filter(Boolean); //1行ずつ問題文を抽出。空の行は削除。 var arr = []; //ランダムで15問のみ抽出して返す for (let i = 0 ; i < 15 ; i++){ let num = Math.floor(Math.random() * str.length); } return arr; }, これで question_allに15問の問題が格納されます。 それをquestion へ1つずつ取り出して、問題を表示しタイピング練習をします。 正解なら次の問題へ行き、最後の問題になったら成績ウィンドウを表示しますが、その辺りは省略します。 Unicodeで文字の範囲を指定したのは、このタイピング正誤判定ロジックでは対応できない漢字などを排除したかったからです。 かといって英語だけに限定したくなかったので、ローマ字やキリル文字、ギリシャ文字などを含むアルファベットの文字を示すUnicodeのざっくりとした範囲を設定しました。 参考:Unicode一覧 0000-0FFF - wikipedia オリジナル問題の読み込み このタイピング練習アプリでは、独自の問題を使えるという点が特徴です。 csvファイルをアップロードする仕組みを作り、あとのロジックは前述の「問題文の読み込み」と共通のfunctionを使います。 csvファイルのアップロード inputでtype="file" のボタンを設置します。loadCsvのメソッドを設定します。 <input type="file" @change="loadCsv"> loadCsvは次のように記述し、前述の を使います。 loadCsv(e) { let file = e.target.files[0]; let reader = new FileReader(); if (!file.type.match("text/csv")) { this.errorMessage = "Chose only csv file."; return; } reader.readAsText(file); reader.onload = () => { let data = reader.result; localStorage.setItem('questions_all', data); this.questions_all = this.convertCsvStringToArray(data); }; } 参考:Vue.js CSVファイルを読み込み表示[FileReader] 本番公開 本番公開はNetlify、Github Pageなどで行えます。 Vue.jsしか使っていないので、DB環境の構築などは不要です。 筆者はLaravelを使うことが多いため、Forge Laravel で本番公開しました。Forge Laravelでvueアプリを公開する方法については別記事にまとめてあります。 Laravel Forgeにvue.jsだけのSPAをデプロイする方法 最後に 実用性と「動くこと」を第一にコードを書きました。 「もっとこういうロジックがある」というようなコメントがあれば、ぜひお願いします。 なおデザインの部分はCSSフレームワークBulmaのこちらのテンプレートを使っています。 Bulma、余分なjsが無く、使いやすくて良いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vuetifyのv-data-tableの日付時間のformat方法

FirebaseにてTimestampの書き込み方法を created_at: firebase.firestore.FieldValue.serverTimestamp() とした時に、Vuetifyのv-data-tableで表示形式を指定する方法を共有します。 stackoverflowでも、議論されていますね。 もっとシンプルにできたでので、簡単に説明します。 (必要部分のみ) ・templete部分 <v-data-table :headers="headers" :items="item"/> ・script(data)部分 headers: [ { text: '作成日時', value: 'created_at'} ], item: {}, ・script(methods)部分 var itemBox = [] // 略 firebase.firestore().〜〜〜get(). とか data.created_at = moment(doc.data().created_at.toDate()).format('yyyy-MM-DD HH:mm:ss'); // 略 this.item = itemBox; 日付形式に変換した物をmomentを使ってformatする という単純なものでした。 ちなみにワタクシ、あちこちググったり結構ハマってしまいました。 頭が空っぽになっている時に「はっ」と気づきました。 思考転換のためのリフレッシュも大事ですね!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Firebaseとフロントエンドのみで作ったオンラインゲーム『バトルアクターズオンライン』をリリース

どんなゲーム? RPGの戦闘部分のみ切り出したようなオンライン対戦ゲームです (会員登録不要・完全無料) 2~4人までのオンライン対戦とオフラインで遊ぶことも出来ます また、チャット機能やコマンド入力までの時間制限も付けました 技術スタック 言語 typescript フレームワーク vue.js データベース Firebase RealtimeDatabase ホスティング Firebase バックエンド 無し(サーバレスと呼ばれる Google Apps Script や AWS Lambda も使用していません) なぜ作ったのか サクッとオンラインゲーム遊びたい・対戦したい ということがありますが 会員登録が不要のゲームが無く、長い会員登録のあと長いチュートリアルをやって ようやくゲームが出来るというモノばかりだと思った 最近のゲームは課金ドリブンで、金で殴るゲームばかりだなと思い プレイヤースキルが試されるゲームを作りたかったから RealtimeDatabaseでゲームが作れる!みたいなのをよく目にしたもんですが、実際出来るのかどうかと言うのを試してみたかった (下記記事の応用って感じですが) 開発時に注意したこと 一番気を使ったところが、 オンラインゲームのなのでホスト・クライアント同士で齟齬が発生しないか 無料枠に収めるためになるべくRealtimeDatabaseの通信量を抑える アニメーションで画像表示時に遅延しないようにプリロードをする というところです ダメージ計算も全てフロントエンドで行っていますが ホストで計算を行い、各クライアントに返すようにしています(これが基本だとは思いますが) また、通信量を抑えるために、メッセージの送信は行わずEnumで定義したKeyをクライアントに送信し、クライアント側でEnumからメッセージを作り直して表示するようにしました アニメーションの遅延の件ですが、はじめはアニメーション実行時にサーバに画像取得するようにしていました しかし、1回目のアニメーション表示時に飛び飛びになってしまってアニメーションと呼べるものではありませんでした そこで、プリロードを行うことによって、キャッシュから画像を取得され、遅延なくアニメーションが表示出来るようになりました リリース後に分かったこと 「開発時に注意したこと」のときに「RealtimeDatabaseの通信量を抑える」ということを注意して開発し、RealtimeDatabaseの通信量に関しては問題ありませんでした しかし・・・Hostingの方の通信量がヤバかったです・・・ キャラグラフィック・アニメーション・サウンドエフェクト等のアセットを使用しており 1つ1つは100kbもいかないくらいなのですが、プレイヤーが増えるたびに読み込まれて大変でした リリース直後150人程度にプレイしてもらって600MBの読み取りくらいだったと思います これに関しては、一番容量の食っていたキャラグラフィックを縮小したり圧縮したりで一応改善しました 課題 課題としてはRealtimeDatabaseにゴミデータが残ってしまうことがあるということです プレイヤー参加時にDBに追加、退出時にDBから削除というような処理があるのですが ブラウザバックではなく、ブラウザを強制終了した場合退出の処理が走らないのでゴミデータが残ってしまいます バックエンドが無いので、ここらへんの処理がどうすることも出来ず・・・。ということがあります GASを使って定期的にお掃除するのが一番いいのかなとは考えています 最後に オンラインゲームはプレイヤーが居てなんぼのものなので 良かったら遊んでやったください
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む