Vue.jsでローディング表示を実装する

ローディング表示モジュールの調査 vue.jsでローディング表示を行う場合、ローディング表示に関係するモジュールについて調査する。 出来れば、 実装が簡単 よく見かけるような見た目(独自性がない) メンテされている という条件にあてはまるものを採用したい。 調べた結果を以下の表にまとめた。 名前 種類 GitHub Star 最終更新(2020/05/06時点) 備考 vue-loading Vueコンポーネント 2018/12/22 紹介している記事が多い vue-spinner Vueコンポーネント 2017/10/07 Vue2.0をサポートしていない Single Element CSS Spinners css 2019/12/09 よく見かける見た目 vue-loading-overlay Vueコンポーネント 2020/04/18 全画面に表示するらしい vue-wait Vueコンポーネント 2019/10/08 だいぶ機能がリッチそう ajaxload.info gif - - よく見かける見た目 調べて出てきた候補は以上。...

May 6, 2020 · 1 min

都道府県間通勤・通学を考慮したパンデミックシミュレーションもどき

先日、SEIRモデルを用いた感染症流行のシミュレーションを行った。 このプログラムを少し拡張して、都道府県間通勤・通学を考慮したパンデミックシミュレーションもどきを行う。 ※本シミュレーションや上記リンク先のシミュレーションは、実測値等には全く基づいていないため、完全に空想上のシミュレーションになります。 本シミュレーションの結果が実情を反映していたり、今後の予測を示していたりはしません。 都道府県間通勤・通学をシミュレーションに組み込む 都道府県間通勤・通学の影響をシミュレーションに組み込むため、総務省統計局「平成27年国勢調査結果」1を参考にする。 今回は東京都・群馬県・栃木県・茨城県・埼玉県・千葉県・神奈川県間の自宅外就業者数及び通学者数データを扱う。 モデルへの組み込み方としては、移動用のグループを形成し、移動用のグループは移動先のデータと感染率を共有するという方法を採る。 なお、今回はシミュレーション内時刻が8:00の時に通勤・通学者が一斉に(移動時間0で)移動し、シミュレーション内時刻が17:00の時に通勤・通学者が一斉に(移動時間0で)帰宅すると仮定する。 東京都と千葉県間の人口移動を例にして説明する。 まず、初期状態として以下のような状態になっているとする。 値はすべて適当だが、東京都に10人感染者(\(I\))がいるとする。 この後、時間を進行させる。 シミュレーション内の時刻が8:00になった時、人口移動用のグループを分割する。 移動用グループの総人数は総務省統計局「平成27年国勢調査結果」1における自宅外就業者数及び通学者数に従う。 \(S:E:I:R\)比は移動元の都道府県データの比と等しくする。 ここで、移動用グループは移動先の都道府県のデータと、感染率\(\frac{R_0I}{iN}\)を共有する。 感染率を共有させた状態で、時間を進行させる。 なお、感染率を共有する関係で、非感染者から潜伏感染者への遷移に関する項については時間刻みに対して1次精度になってしまう。 シミュレーション内の時刻が17:00になった時、人口移動用のグループを移動元のデータに合流させる。 上の図中の値もすべて適当だが、以上のような形で、都道府県間の感染伝播をシミュレートする。 計算する 人口データについて 人口データは各自治体のページを参考に、以下の値を使う。 都道府県 人口[人] 備考 東京都 13951635 2020年1月1日時点推計2 茨城県 2866325 2020年1月1日時点推計3 栃木県 1942313 2019年10月1日時点推計4 群馬県 1938053 2019年10月1日時点推計5 埼玉県 7341794 2020年4月1日時点推計6 千葉県 6280344 2020年4月1日時点推計7 神奈川県 9204965 2020年4月1日時点推計8 各都道府県毎の通勤・通学による流入・流出人口は総務省統計局「平成27年国勢調査結果」1より、以下の値(単位は[人])を使う。縦が流出元で横が流出先。...

May 5, 2020 · 1 min

感染症数理モデルについて触りの部分だけ学ぶ

目的 特にしっかりした目的はない。 なんとなく数値シミュレーションについて学び直したくなったため、現在身近にある現象を題材にして学ぶ。 ネットの情報を参考に、適当にシミュレーションを走らせてみる。 ※本シミュレーションは、実測値等には全く基づいていないため、完全に空想上のシミュレーションになります。 本シミュレーションの結果が実情を反映していたり、今後の予測を示していたりはしません。 今回扱うシミュレーションモデル SEIRモデルを扱う。 SEIRモデルとは SEIRモデル(エスイーアイアールモデル)とは感染症流行の数理モデルである。 モデルは 感染症に対して免疫を持たない者(Susceptible) 感染症が潜伏期間中の者(Exposed) 発症者(Infectious) 感染症から回復し免疫を獲得した者(Recovered) から構成され、その頭文字をとってSEIRモデルと呼ばれる。 (Wikipediaより) モデル式は以下のような式で表される。 $$ \begin{aligned} \frac{dS}{dt} &= m(N - S) - bSI &(1) \cr \frac{dE}{dt} &= bSI - (m + a)E &(2) \cr \frac{dI}{dt} &= aE - (m + g)I &(3) \cr \frac{dR}{dt} &= gI - mR &(4) \end{aligned} $$ ここで\(t\)は時間、\(m\)は出生率及び死亡率、\(a\)は感染症の発生率、\(b\)は感染症への感染率、\(g\)は感染症からの回復率を表す。 また\(N\)は全人口を示し、 $$N \equiv S + E + I + R (5)$$...

May 2, 2020 · 2 min

Chart.jsで時刻データを扱う

Chart.js公式のドキュメントを参考にして、Chart.jsで時刻データを扱う場合の描画オプションについて確認する。 入力データ 入力データはx軸データをy軸データを各点それぞれ指定する。 今回はx軸データに時刻データを使う。 例としては、以下のように指定すればOK。 data: [{ x: '1995-12-17T00:00:00', y: 1 }, { x: '1995-12-18T00:00:00', y: 10 }, { x: '1995-12-21T00:00:00', y: 20 }, { x: '1995-12-25T12:00:00', y: 30 }, { x: '1996-01-01T00:00:00', y: 40 }] データフォーマット 時刻スケールのデータを使う場合、フォーマットはMoment.jsが扱えるフォーマットであればどういった形式でも良い。詳細はMoment.jsのドキュメント参照。 描画オプション 時刻目盛りを扱う場合、以下のオプションを設定できる。 adapters.date 外部の時刻ライブラリ(つまりMoment.js以外)を使うためのオプション。 distribution データのプロット方法。 指定できる値はlinearまたはseriesのいずれか。 初期値はlinear。 linearはデータ描画間隔が時間間隔に応じて変化する。 seriesはデータ描画間隔がすべて同じになる。 以下に同一データを用いてdistribution設定のみ変えた場合の描画例を示す。 linearを指定した場合 var ctx = document.getElementById('distribution_linear').getContext('2d'); var chart = new Chart(ctx, { // The type of chart we want to create type: 'line', // The data for our dataset data: { datasets: [{ label: 'linear', backgroundColor: 'rgb(255, 99, 132)', borderColor: 'rgb(255, 99, 132)', fill: false, data: [{ x: '1995-12-17T00:00:00', y: 1 }, { x: '1995-12-18T00:00:00', y: 10 }, { x: '1995-12-21T00:00:00', y: 20 }, { x: '1995-12-25T12:00:00', y: 30 }, { x: '1996-01-01T00:00:00', y: 40 }] }] }, // Configuration options go here options: { scales: { xAxes: [{ type: 'time', //!...

April 26, 2020 · 9 min

Vue.jsを使ったSPAにおいてTwitter等でのリンク表示がいい感じになるようにする

Vue.jsでSPAを構成した際、TwitterなどのOGPが上手く表示されなかったので、対処した。 SPAとは?→シングルページアプリケーション この記事で扱っているSPAとは、シングルページアプリケーションを指す。 SPAについては少し以下の記事で触れたが、詳細は他のサイトの方が詳しいと思う。 OGPとは?→Webページのリンクを表示する仕組み OGPとはOpen Graph Protocolの略で、TwitterとかFacebookとかでリンクがいい感じに表示されるアレに使われているプロトコルのこと。 ↓これ。 Chart.jsで横軸が日付のグラフを作成する https://t.co/evu4HqqQ4f @aoki_kouyaさんから — 青木晃也 (@aoki_kouya) April 4, 2020 webサイトをいちから作る際、OGP対応していないと、Twitterとかでリンクを貼り付けても画像や説明文は表示されない。 そこらへんはTwitter側でなんとかしてくれるわけではなく、サイト作成者側が適切にOGP設定を行う必要がある。 SPAの場合はOGP設定にひと工夫必要 OGPは、具体的にはHTMLにmetaタグを設定することで対応できる。 例えば、以下のようなmetaタグを<head>要素内に設定する。 上記は私が作成したサイトの実装例になるが、他のサイトを調べると、head要素にprefix属性を適切に設定する必要があるようだ。 私は設定していなかったが、とりあえずTwitterあたりでは問題なく動いているように見える。 まあ、正しい対応ではないと思う。 このOGP設定だが、SPAの場合はひと工夫必要になる。 理由は、OGPによってリンクを作成する際、JavaScriptが動かないケースがあるため。 OGPによってリンクを表示する際、クローラーと呼ばれるプログラムによって、リンク先のページをスキャンする。 スキャン結果に従ってリンクを表示するのだが、TwitterやFacebookのクローラーはJavaScriptを実行してくれないらしい。 よって、JavaScriptによってmetaタグを生成しても、リンクには反映されない。 SPAでOGP設定を適切に行う場合はここら辺の対処が必要。 今回は特定条件時のみ静的ページを返すように実装 今回の結論、解決策になる。 調べてみると、(Vue.jsを用いた)SPAでのOGP設定については色々対応策があった。 いくつか参考にさせていただいたページを挙げておく。 上記のページの方法はページ内にも書かれている通り、全てのページで同じ内容のOGPになってしまう。 今回はそれぞれのページで異なるOGPを設定したいため、同じ方法はとらなかった。 上記のページは詳しく書いてあり、参考になりそうだったが、Firebaseを使ってない、使ったことがないため今回は同じ方法をとれなかった。 最終的には以下のページの方法を真似させていただいた。 上のページの方法は、TwitterやFacebookなど特定のクローラーに対してのみOGP対応用のテンプレートを返すというものになっている。 アプローチとしては一番最初に挙げたページと同じだが、こちらはクローラー検出用にControllerを作成して、テンプレートの出し分けをしている。 比較的容易に実装でき、ページごとに異なるOGP設定ができそうだったため、こちらの方法を採用した。 この方法の課題としては、OGP対応用のテンプレートを返す相手をピンポイントで指定する必要があるため、明示的に指定したクローラー以外に対しては対応できない点がある。 また、OGP対応用のControllerを新規に作成する必要があり、Controllerが単純に1個増える。 なお、各サービスのクローラーの情報は以下のサイトを参考にさせていただいた。 雑記 Twitterでのリンク表示内容確認には以下の公式のサイトが便利。 これからはじめるVue.js実践入門 山田 祥寛 Amazon Kindle 楽天 楽天Kobo

April 25, 2020 · 1 min

Chart.jsで横軸が日付のグラフを作成する

webサイト上で横軸が日付情報のグラフを作りたかったのでChart.js周りで色々調べた。 横軸が単純な数値じゃない場合は面倒くさくなるかなと思っていたが、Chart.jsが非常に使いやすく、すんなりできた。 最終的に作ったもの 画像で貼ろうと思ったが、結構サイズが大きいのでリンクで貼り付けておく。 Chart.jsとは グラフ類を描画するためのJavaScriptライブラリ。 HTMLの<canvas>要素に2Dグラフィックを描画できる。 ライセンスはMIT。 Chat.jsのインストールと使い方 基本的な使い方を公式に従って確認してみる。 インストール 今回はとりあえず手軽そうなCDNを使う。 よってHTMLに以下のタグを追加する。 <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script> なお、ここで Chart.bundle.min.js を選択したのは、今回日付データを扱うため。 Chart.min.js の方は日付データを扱うためのライブラリMoment.jsが含まれていない。 使い方 HTML側はグラフ描画用の<canvas>タグを作成する。 先ほどのCDNの参照及び今回作成するJavaScriptの読み込みを合わせて、HTML側のソースは以下のようになる。 index.html JavaScript側は公式のサンプルを参考にして以下のようにする。 main.js これら2つのファイルを適当なところに保存して、index.htmlをブラウザで開く。 以下のようなグラフがブラウザ上に表示される。 横軸が日付情報のデータをプロットする サンプルが動いたので、今回扱いたい、横軸が日付情報のデータをプロットする。 HTML側は特に変更せず、JavaScript側を以下のように変更する。 main.js 参考ページ main.jsを上記のように変更し、index.htmlをブラウザで開くと以下のようなグラフが描画される。 横軸が日付になっており、横軸の間隔もデータに合わせていい感じになっている。 まとめ Chart.jsを使って横軸が日付情報のデータをプロットできた。 色々と描画オプションがあるようなので、それぞれ変更させるとどのようにグラフが変化するか、また今度まとめたい。 確かな力が身につくJavaScript「超」入門 第2版 狩野 祐東 Amazon Kindle 楽天 楽天Kobo

April 5, 2020 · 1 min

Laravel+Vue.jsでSPA(シングルページアプリケーション)を作成した

今回作成したサイト 今回作成したサイトは以下のサイト。 ClubPage 私が所属している電子工作サークルのホームページを作った。 このブログからcssを流用しているので、見た目がだいぶ似ている。 構成 Laravel Vue.js バックエンドはLaravel、フロントエンドはVue.jsを使っている。 シングルページアプリケーションとは 今回はシングルページアプリケーション(SPA)という構成を採用した。 シングルページアプリケーションとは シングルページアプリケーション(英: single-page application、SPA)とは、単一のWebページのみから構成することで、デスクトップアプリケーションのようなユーザ体験を提供するWebアプリケーションまたはWebサイトである。必要なコード(HTML、JavaScript、CSS)は最初にまとめて読み込むか[1]、ユーザの操作などに応じて動的にサーバと通信し、必要なものだけ読み込みを行う。 Wikipediaより というものらしい。 これまでRuby on RailsやDjangoとかを使ってwebサイトを作ってみてきたが、どれも各ページ毎に、サーバ側でHTMLの生成を行うマルチページアプリケーションだった。 今回はLaravelでwebAPIを作成し、そのAPIから取得した情報を、Vue.jsを使ってブラウザ上に表示するような構成にした。 なぜSPAにしたのか 理由は1つで、今回参考にしたサイトがSPAを採用していたから。 今回参考にしたサイトは以下のサイト。 このサイトにあるチュートリアル、書かれている情報量がかなり多くて、これだけの情報をタダで得られるのが信じられない。 今回初めてLaravelとVue.jsを触ったが、このサイトのおかげで色々と基礎を学ぶことができた。 今回学んだこと、感じたこと インタフェース部とエンジン部の分離はやはり重要 今回の構成はAPI(Laravel)と表示部(Vue.js)を分離している。 たとえばhttps://home.lchika.club/api/tagsにアクセスすれば、Laravelの機能によって、タグの一覧をJSON形式で取得できる。 こういったAPIから取得した情報をVue.jsで処理して、ブラウザにレンダリングする。 このように分離することで、UIを変えたいときは、基本的にVue.jsの部分のみを修正するだけですむ。 Laravelの処理部は一切手を加える必要がない。 まあ、一般的なwebフレームワークを使っていれば、実装の分離は適切に行われているが、ある一部分のフレームワークをごっそり切り替えることはできない。 今回の構成では、例えばフロントエンドにReactを使いたければ、Laravel部分はそのままで、フロントエンド部分をごっそり切り替えられる(と思うけど、Laravel-mixとかの関係で難しいのかもしれない…)。 このように、インタフェースとエンジン部の分離で得られる効果はやはりでかいなと思った。 ローディング表示がないとwebサイトの質が落ちる これは個人的な印象かもしれないが、ローディング画面の表示はユーザにとって(ある程度)重要だなと思った。 現状ではローディング表示は実装していないため、読み込み直後は一部のコンテンツが表示されていないし、一部のコンテンツについては結構な時間表示されないことがある。 これはサイト利用者側からすると、違和感を覚える要因になり、満足度の低下につながると思った。 YouTubeとかもローディング中はコンテンツ表示部をグレーで表示したりしている。 最初はこれ意味あるのか?と思っていたが、今回自分でJavaScriptを多用したサイトを構築してみて、こういった対応も重要だなと思った。 WYSIWYGエディタの選定は毎回の課題 今回はブログのようなサイトを構築したので、フォームから記事を投稿できる必要があった。 さすがにHTML直打ちで入力はできないし、リッチテキストエディタを採用する必要があった。 毎回どのリッチテキストエディタを使うか苦労するが、今回も例に漏れず苦労した。 とりあえず今のところはCKEditorを使っている。 ただ、まだ課題があって、iframeの挿入が上手くいっていない。 いつも大体、リッチテキストエディタまわりは 画像の挿入 画像の整形 外部コンテンツの挿入 目次の作成 あたりで詰まっている。 今回はまだ目次の作成について考えていないので、目次が必要になった時に多分また詰まる。 SPAのパフォーマンス向上はバンドルサイズの削減こそ正義 今回作成したサイトのパフォーマンス向上については以下の記事に書いた。 最初特に何も考えずにサイトを作っていたら、パフォーマンスが崩壊した。 今もパフォーマンスが良いとは言えないが、バンドルサイズを削減することで、パフォーマンスが向上した。 こういったパフォーマンス向上のための施策は必要不可欠だなと感じた。 まとめ 今回はLaravelとVue.jsを使ってサイトを作った。...

March 15, 2020 · 1 min

Laravel+Vue.jsでLighthouseのスコアを0点から97点にした(バンドルサイズ削減)

Laravel+Vue.jsで作成していたwebサイトの応答速度が激遅だったので、対策を実施した。 環境 Laravel 6.14.0 Vue.js 2.6.11 対策前はページロードに20秒かかっていた 特に何も考えずにwebサイトを作っていたら、トップページのロードに20秒ほどかかっていた。 これではさすがにwebサイトとして成立しない。 Googleが提供しているwebページ分析ツールLighthouseを使ってパフォーマンスの測定を行ったところ、以下のような結果になった。 堂々の0点である。提示されている対応策の詳細を見ると、以下のように書かれていた。 どうやらバンドル後のapp.jsのサイズが約4MBと、超巨大になっているらしい。対応策としてapp.jsのサイズ削減を行った。 対策1:本番用ビルド設定を適用する バンドルサイズ 3.86MB(app.js) → 1.59MB(app.js) 解説 そもそもビルド設定が間違っていた…。ビルドコマンドとして npm run dev を実行していたが、これは開発用のビルドコマンドらしい。 本番用のビルドコマンド npm run prod を実行したところ、バンドルサイズは3.86MB→1.59MBと、約40%になった。 Lighthouseの結果 0点→10点に上昇した。 対策2:gzipで圧縮する バンドルサイズ 1.59MB(app.js) → 395KB(app.js.gz) 解説 以下のページを参考に、gzipでapp.jsを圧縮した。 そのままコピペで適用できた。 Lighthouseの結果 10点→63点に上昇した。 対策3:ページごとにJSファイルを分割する バンドルサイズ 395KB(app.js.gz) → 243KB(app.js.gz) 解説 以下のページを参考に、ページごとにJSファイルを分割した。 こちらも特に詰まることはなく、ほぼコピペで実装できた。 この対策を実装したことで、ビルド後のJSファイルが以下のように、分割されて生成されるようになった。 Lighthouseの結果 63点→87点に上昇した。 対策4:bootstrap-vueの選択的インポート バンドルサイズ 243KB(app.js.gz) → 129KB(app.js.gz) 解説 対策1~3で、あらかた大きなところは対策できたと思ったので、より細かいところを対応するため、webpack-bundle-analyzerを使ってバンドル結果の分析をした。 webpack-bundle-analyzerの出力結果は以下のようになった。 この結果から bootstrap-vue ckeditor lodash あたりのサイズが大きいらしいことが分かった。...

March 8, 2020 · 1 min

カメラ画像から対象物の向きを検出する(OpenCV)

やりたいこと 俯瞰で見ているUSBカメラの画像を使って、自律的に動いているロボットの向きを検出する。 また、カメラ画像における指定の座標と、ロボットがなす角を算出する。 動作環境 ターゲットボード JetsonNano OS Ubuntu 18.04.4 LTS 使用ライブラリ Python版 OpenCV 4.1.1 処理結果 今回実装した処理の結果は、画像で示すと以下のような感じになる。 方法 今回実装した方法は以下の通り。 カメラ画像をHSV形式に変換 カメラ画像のうち指定のHSV範囲に従ってマスク画像を作成 マスク画像から輪郭を抽出し、1番面積の大きい領域のみ残したマスク画像を作成 カメラ画像とマスク画像の共通領域を抽出 4.で作成した画像から黒色領域を抽出 5.で抽出した黒色領域のうち、1番面積の大きい領域の重心p1、2番目に面積の大きい領域の重心p2を計算 p2からp1へのベクトルと、p1とp2の中点から指定の座標へのベクトルのなす角を計算 処理順に従って中間生成画像を並べると以下のような感じになる。 元画像 手順3.で作成したマスク画像 手順5.で抽出した黒色領域 手順6.で算出した各黒色領域の重心 処理結果 ソースコード 一部自作モジュールもimportしているのでコピペでは動きません。 呼び出し方は例えば以下のように。 処理時間や実行時のリソース使用量など 処理時間 今回の一連の処理呼び出しにどれだけ時間がかかっているか計測したところ、以下の通りだった。 elapsed_time:0.49050045013427734[sec] elapsed_time:0.500530481338501[sec] elapsed_time:0.49204468727111816[sec] だいたい0.5秒ほどかかっている。このままだとリアルタイム性が求められる場合は使えない。 リソース使用量 Jetsonのモニタツールjtopの出力は以下のような感じ。 プログラム稼働中 GPUが稼働していない。GPUを使うようにすれば高速化できるのだろうか(全然そこらへんは調べていない)。 なぜこの処理を実装したか 全体を俯瞰できるカメラの情報を使って、ロボットを指定位置に誘導したかった。 カメラ側がロボットに指定の位置に対する角度・距離情報を伝え、ロボット側でその情報を使って、モータ値を計算する。 設計の経緯や苦労したところなど 目印をどう設計するか 向き検出のための目印をどう設計するかが、検出精度や処理速度に最も影響を与える部分だと思う。 今回は黄色の画用紙の上に、面積の異なる黒色の画用紙を2つ(前方に面積が大きいもの、後方に面積の小さいもの)つけて目印にした。 単純だが、思っていたより認識出来ていたと思う。しっかりしたベンチマークはとっていないが。 最初はQRコードの活用を考えていた。OpenCVにはQRコード認識処理が実装されており、向きも検出出来そうだったので。今後複数台ロボットを同時に動かすことを考えても、QRコードだったら文字列情報を付加できるので、各ロボットの識別に使えそうとも思っていた。 ただ、ある程度QRコードが大きく写っていないと認識できなかった。今回はカメラと認識対象ロボットの距離が遠い時でも認識できるようにしたかったので、QRコード案はやめた。...

February 24, 2020 · 1 min

VTuberの簡易ランキングサイトを作った

概要 適当に抽出したVTuberについて、チャンネル登録者数増加数のランキングサイトを作成した。 1日1回、午前5時30分ごろ更新。 構成 Golang + Gin + Bootstrap 雑記 Golangを使ったwebアプリを初めて作成した。Golangは未使用の変数、importがデフォルトでコンパイルエラーになるのが印象的だった。ルールが厳格な印象。 YouTubeの現在の仕様で、チャンネル登録者数が多いほど、刻み幅が大きくなる。その刻み幅分を超えないと、増加量が0になってしまうので、1日単位だと正確なランキングにならない。 今回のサイトを作るにあたって、既存サイトを調べてみた。色々凝っているサイトが多数あった。やはりここら辺(YouTube周り)は色んなビジネスが成り立っているんだろうなと思った。 改訂2版 みんなのGo言語 技術評論社 Amazon Kindle 楽天 楽天Kobo

January 17, 2020 · 1 min