まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

ふとしたきっかけがあって PWA(Progressive Web Application) を作る機会がありました。今回は PWA の中でも特にキャッシュ機能を試すことが主目的だったのですが、最低限の機能を実装して公開してみたので、興味ある方は以下を参照して使ってみてください。


【PWA とは】
主に Google 主導で進められているモバイル端末向けウェブアプリケーションの技術で、「モバイル端末でウェブアプリケーションを利用する際に、ネイティブアプリであるかのような UI や動作を可能にする」ことを主目的としています。

なお PWA 自体の説明をすることが本ブログエントリの目的ではないし、そこまで含めてしまうと長くなりそうなので、興味ある方は適当にググってください。


【アプリの内容とシステム構成】
PWA には特徴的な機能がいくつかありますが、今回は特に「キャッシュ機能」を確認するためのアプリケーション実装を行いました。実際のアプリ(パズルゲーム)を使うにはスマートフォンのブラウザで以下の URL にアクセスしてください:
https://pwa-slidegame.mybluemix.net/


正しくアクセスすると以下のような画面が表示されます:
2020020301


このままアプリの実行を続けてもいいのですが、せっかくの PWA なので「インストール」してみます。メニューから「ホーム画面に追加」を選びます(下図は iPhone Safari での場合):
2020020302


正しく追加できるとホーム画面に以下のようなアイコンが追加され、次回からはここをタップすることで同じアプリを起動できるようになります。というわけでこちらをタップします:
2020020303


先程に似た画面が表示されます。ただアドレスバーなどは表示されておらず、PWA として起動してネイティブアプリっぽく起動しています:
2020020304


「(カテゴリーを選択)」と書かれた部分をタップすると、この後選択する画像のカテゴリー一覧が表示されます。実際には色々なカテゴリーがあっていくつか試すこともできるのですが、キャッシュの説明のため以下は「こども」カテゴリーを選択したものとして(それ以外のカテゴリーは選択していないものとして)説明を続けます:
2020020305


カテゴリーを選択すると、「いらすとや」の選択したカテゴリーの画像がカルーセル表示されます。画像を右や左にフリックすることで次の画像や前の画像を表示できます:
2020020306


カルーセルから「パズルにしたい画像」を選んでタップします。では↓の画像を選んでタップしたものとして以下を続けます:
2020020307


すると選択した画像が 4x4 のスライドパズル化され、実際に遊ぶことができるようになります:
2020020308


(簡単なパズルではないのですが・・)パズルを進めていって、完成すると、・・・
2020020309


パズル完成までに要した時間と動かした回数が表示されます:
2020020310


続いて過去の(回数の少ない)トップ10が表示されます。直近の記録がこの中に含まれていれば強調表示される、というゲームです:
2020020311


ここまではネットワークに接続された状態で行いました。PWA ではデータをキャッシュすることで、オフラインでもある程度の利用が可能になります。その部分を試してみましょう。この時点で起動していた PWA アプリをいったん終了(タスク一覧から終了)しておいてください。

まずはスマホをオフライン状態にします。WiFi もモバイルデータも接続されていない OFF の状態に設定します:
2020020312


あらためてホーム画面のアイコンからアプリを起動します。先程起動した時に表示されたトップページは自動的にキャッシュされていて、ネットワーク接続がなくても表示され、カテゴリー選択状態になります:
2020020313


カテゴリーとして「こども」を選択した場合も先程の実行時にキャッシュできているので、ネットワーク接続がないにも関わらず画像含めて表示することができています。なお、ここで表示されているのはあくまでキャッシュに含まれている画面であって、ネットワーク接続時の最新状態が表示されているわけではありません:
2020020314


しかし先程選択しなかったカテゴリー(例えば「職業」)を選択すると、こちらの内容は接続状態でのキャッシュが存在していないため、カルーセルの中身を取得することができず、何も表示されない、という状況になります。ある意味でキャッシュが有効に動いていることが確認できます:
2020020315


またオフラインでもパズルクリアまではできますが、その後のデータ記録目的での HTTP POST には失敗します:
2020020401



といったオフライン時にキャッシュ済みのデータを使って一部動かすことができるようになるのが PWA のキャッシュ機能です。


この PWA アプリケーションは以下のようなシステム構成となっています。構成そのものはウェブアプリケーションのシステム構成そのもので、この中で「いらすとや」のページをリアルタイムにスクレイピングしてカテゴリー一覧やカテゴリーの画像一覧を取り出して、アプリケーションの中で利用しています。アプリケーションそのものにキャッシュの機能は含まれていません:
2020013101



【PWA でのキャッシュの実現方法】
アプリケーションを PWA 化する際にいくつか設定のためのファイルを追加するのですが、それらの準備が完了していると、以下のような仕組みでキャッシュが(自動的に)実現されます。

まず、キャッシュデータが全くない状態でオフライン操作することはできません。画像とか API の実行結果とか以前に、トップページの HTML がないと何も表示できません。つまりオフラインでキャッシュ表示するためにはオンライン時にある程度の情報をキャッシュしておく必要があります。PWA では オンライン時に HTTP GET する際のパスとその結果を自動的にキャッシュします。上述の説明で行った流れをキャッシュの中身を意識した上で再度理解しておきましょう:
2020013102


そしてスマホがオフラインとなった後に PWA を起動すると、キャッシュの中身を使いながらオフラインで動作します:
2020013103


ただ(オフラインなので当然ですが)キャッシュにない HTTP GET は使えませんし、HTTP POST でデータをサーバーに送信することもできません:
2020013104


このアプリケーションのソースコードはこちらで公開しています。Node.js 上で動かすことができますが、PWA として稼働させるには HTTPS アクセスが必須となります。実際に自分のサーバーで PWA として動かす場合は HTTPS アクセスできるサーバーへデプロイしてお使いください:
https://github.com/dotnsf/pwa-slidegame


CSS で画面内の特定要素に回転をかけることができる、ということを知り、その様子を視覚的に確認できるサービスを作って公開してみました。

この技術(というほどのものではないけど)は CSS の tranform 属性を使って、回転軸と回転角度を指定することで実現できます。ともあれまずは実際に挙動を確認してみましょう:
https://dotnsf.github.io/transform-rotate/


上記 URL にアクセスすると以下のような画面が表示されます。画像(デフォルトではいらすとやさんの「コンピュータを使うペンギン」のイラスト)と、その下に3つのスライダーバーが表示されているはずです:
2020020101


x のスライダーバーを動かすと、動かした角度だけ画面が縦方向に回転します:
2020020102


y のスライダーバーを動かすと、同様に横方向に回転します:
2020020103


z のスライダーバーは画面と平行に回転します:
2020020104


x, y, z のスライダーバーを同時に動かすこともできます。縦、横、平行すべて指定したぶんだけ回転して画像が表示される、ということがわかると思います:
2020020105


これらはすべて CSS の transform 属性だけで実現しています。以下、その技術的な内容を紹介しますが、前提として x, y, z という軸の名前とその意味、そして立体的な位置関係を理解しておく必要があるので、そちらから説明します。以下の図のような関係になっていると理解してください:
20200201


図のような x 軸、y 軸、z 軸があって、自分は z 軸正方面から画面を見ています。実際に見えている画面は x 軸と y 軸からなる平面上に描かれています。

そしてスライダーバーはそれぞれ x 軸を中心に回転、y 軸を中心に回転、z 軸を中心に回転するスライダーバーになっていて、それぞれ指定した角度だけ回転した結果が画面に表示されます。そのため(結果的には)x で回転すると縦方向、y で回転すると横方向に回転したように見えます。また z で回転すると見えている平面上で時計回り/反時計回りに回転しているように見せることができています。

で、これをどう実現しているかという部分が CSS の transform 属性です。例えば id="a" の要素を x 軸中心に 30 度回転させて表示したい場合は、以下のようなスタイルを適用します:
#a{
  transform: rotateX( 30deg );
}

同様にして y 軸中心に 30 度回転させて表示したい場合は以下です:
#a{
  transform: rotateY( 30deg );
}

z 軸中心に 30 度回転させる場合は以下です:
#a{
  transform: rotateZ( 30deg );
}

「30 度」という部分は -180 から 180 まで変えることができます。それぞれの結果は上述のようになります。上述のサービスではこれらのスタイルを各スライダーバーの値を参照しながら動的に変更して表示しており、その結果がこのようになっています。


これはオマケの情報ですが、このサービスではデフォルトでペンギンの画像を表示して回転させていますが、imgurl という画像の URL をパラメータ指定することで表示画像を変更することができます。例えばこの画像を使いたい場合は、画像の URL(https://1.bp.blogspot.com/-A-AUINeSdLY/XexqsbbnoVI/AAAAAAABWiA/1zwr87fQJbsntV_Ez_ky6-RJPRfgeCZ5ACNcBGAsYHQ/s400/kinshi_mark_computer.png)をパラメータとして以下のように指定します:

https://dotnsf.github.io/transform-rotate/?imgurl=https://1.bp.blogspot.com/-A-AUINeSdLY/XexqsbbnoVI/AAAAAAABWiA/1zwr87fQJbsntV_Ez_ky6-RJPRfgeCZ5ACNcBGAsYHQ/s400/kinshi_mark_computer.png


こんな感じで表示できるはずです:
2020020106




各種メディアのニュースでも話題になっていますが、香川県が「香川県の子どもたちがネット・ゲームの長時間の利用により、心身や家族的・社会的な問題を引き起こすネット・ゲーム依存に陥らないために必要な対策を推進し、健全な育成を図るため、本条例を制定しようとするもの」という条例の素案を示しました。具体的には18歳未満の場合、1日にオンラインゲームは60分(土日・祝日・長期休暇中は90分)以内と規定する方針のようです(ただし子供にも保護者にも罰則なし)。


この内容で気になったのは、香川県内のルールだけでなく「ゲーム提供事業者に求める役割」が規定されようとしている点です。具体的には以下の第11条部分が相当します:
香川県の「ネット・ゲーム依存症対策条例案」【全文】

2020012501


※なお、この第11条に相当する事業者および香川県在住者とを対象に2月6日までパブリックコメントを受け付けています:
香川県ネット・ゲーム依存症対策条例(仮称)素案についてパブリック・コメント(意見公募)を実施します


「インターネットを利用して情報を閲覧に供する事業またはコンピュータゲームのソフトウェアの開発、製造、抵抗等の事業を行う者」をどのように解釈するかにもよりますが、僕自身も個人でオープンソースのゲームを作ったり、ネットで誰でも遊べる状態で公開したりしています。例えば来週の IT 勉強会の題材にもしようとしているスライドパズルゲームとかもその1つです。以下の URL にアクセスするだけで遊べてしまいます(遊び方は後述):
https://dotnsf.github.io/slidepuzzle/


↑こういう趣味開発レベルのゲームも「県民のネット・ゲーム依存症の対策に協力するものとする」の対象になっちゃうんですかね? という意見をパブリックコメントで伝える権利を有するのかな?(有する場合は協力しないといけないってこと??)


・・などなど、まあ色々言いたいこともありますが、とりあえず自分なりに考えた上で対策を講じてみました。対策済みのゲームはこちらから遊べます:
https://kawaga-game.mybluemix.net/


上記 URL にウェブブラウザでアクセスすると、以下のような位置情報へのアクセス許可を促すメッセージが表示されるので「許可」を選択してください(以下は FireFox を使った場合の画面です):
2020012502


利用者(=あなた)が香川県以外からアクセスしていた場合、以下のような画面になり、そのままゲームを遊ぶことができるようになります。ゲーム自体はカメラアイコン部分をクリックして、PC内に保存されている画像を選びます:
2020012503


すると選んだ画像が懐かしいスライドパズルとなって遊べる、というものです。一応移動回数やゲームを解くまでの時間がカウントされていて、競技性のある作りにしています:
2020012504


しかしアクセス元が香川県であった場合のみ少し挙動が変わり、画面ロード直後に以下のような警告画面が表示されます。これで上述の第11条で求められる対策努力が講じられているのではないかと自負しております(笑):
2020012505


このゲームのソースコードもこちらで公開しています:
https://github.com/dotnsf/kagawa


具体的な実現方法としては HTML ページの中で GeoLocation API の getCurrentPosition メソッドを実行して現在地の緯度・経度を取得しています。そして取得結果に対して Yahoo! デベロッパーネットワークYahoo! ジオコーダ API を使って緯度・経度を住所に変換し、その住所が「香川県」で始まっているかどうかを識別する、というロジックで実現しています。

少しだけ補足すると、アクセス元の識別はできているので、単なる警告に留めずに実際に利用時間を測定して、1時間を超えることがあったら強制終了、みたいなことができないわけではありません。まあこのゲームに限っては1時間超えても飽きずに遊んでもらえる可能性はかなり低いと思ってますけど・・


・・・どなたかの参考になれば幸いでございます。 (^^;

このページのトップヘ