JavaScriptで時計アプリを作ってリリースした話
成果物
なぜ作ろうと思ったのか
私のバイト先では、卓上デジタル時計のアプリを入れたiPadが時計代わりとして使われています。
ただ、そのアプリは時間だけでなく日付や位置情報に基づく天気情報なんかも表示されており、私はその画面を見るたびに「この情報いらなくね?」と思っていました。
昨今の時計アプリはどれも天候表示、日付表示、アラーム機能、タイマー機能、ウィジェット表示等々の機能は当たり前のように搭載されています。
純正時計アプリがあるなかでサードパーティー製時計アプリの強みはなんなのかというと、画面いっぱいにデカデカと時間が表示されること、ウィジェットにデジタル時計を設置できることくらいです。
それを求めてユーザーはわざわざ時計アプリをダウンロードするわけで、天気も、日付も、アラームも、タイマーも、最強の純正アプリがある手前、普通に蛇足な機能なのではないか。
「時計アプリは時間をでっかく表示してくれればそれで良いんだよ!」
と、世の時計アプリにささやかな不満を抱いていた私は、時計機能だけの時計アプリを自分で作ってリリースしよう!と思い至ったのでした。
開発環境/言語
開発環境はMonacaです。Monacaはアシアル社が運営しているクロスプラットフォーム開発環境で、クラウド上で開発からビルドまで一貫して行うことができます。Githubにも直接Push/Pullでき、HTML/CSS, JavaScriptだけでクロス開発できるので非常に使い勝手がいいです。
なぜReact Nativeではないのか
私は就活を控えた学生で、限られた時間で成果物をたくさん作ってポートフォリオを充実させたい、という背景があります。
しかし、残念なことにまだReact Nativeを触ったことがないので、学習コストを鑑みると、今私が持てる技術で上記の目的を達成するにはMonacaを採用するのが最適解だと考えました。
機能の洗い出し
「時計アプリは時間をでっかく表示してくれればそれで良いんだよ!」
という課題感があるので、時計機能を軸に、なるべく余計な機能を削ったアプリにしようと思いました。
👇とりあえず考えてみた機能がこちら👇
・時計機能
・時計のカスタマイズ(色、フォント)
・ウィジェットに表示
これに加え、全てのアプリに必要な機能として
・不具合報告
・App内レビュー
・他のアプリへの導線
※こちらの記事を参考にさせていただきました👇
競合調査
ユーザーの生の声を知るため、「時計」と調べて上位に出てくるアプリのレビューを読み漁りました。
その結果、多かったのが
・秒数を非表示にできるようにしてほしい(視界がチカチカするから)
・ウィジェットのバグ(時間がずれてる)
・ウィジェットのバグ(iOSのアップデートによる不具合)
・素早く時間を確認したいのにアプリを開いた瞬間に広告が出て邪魔
・アラームがちゃんと動作しない
・タイマーがあればなあ(勉強とかに使いたい)
・秒数の表示/非表示切り替え
👉確かにこれはあったほうが良い(採用)
・ウィジェット
👉バグの温床になりそう。iOSのアップデートごとにこまめなメンテが必要になり、面倒である。そもそも卓上時計として使うアプリなのでホーム画面にウィジェットとして表示する必要がないのかもしれない。ロック画面とかで時間確認できるし。(不採用)
・広告
👉広告と時計アプリは絶望的に相性が悪い。その上、競合アプリに広告なしのものが多く、広告ありのアプリは軒並み低評価を食らっている。(不採用)
・アラーム/タイマー
👉コンセプトに反するため不採用
(別でポモドーロタイマーとか作ってみても面白いかもしれない🤤)
というわけで、検討の結果、実装するのは以下の機能としました。
・時計機能
・時計のカスタマイズ(色、フォント)
・秒数の表示/非表示切り替え
・不具合報告
・App内レビュー
・他のアプリへの導線
実装
時計
時計機能はnew Date();
で時間を取得してそれを表示するだけです。
時間を取得して表示する関数をsetInterval()
するのがJavaScript時計の基本なんですが、このままだと、微妙に時間がずれてしまいます。
というのも、例えばsetInterval(hoge(),1000)
とした場合、毎秒hoge関数が発動するわけですが、その起点が00ミリ秒からずれていた場合、その分だけ実際の時間とhoge()
で表示する時間がずれます。
hoge()
の最初の発動が21時21分21秒210ミリ秒だとすると、本来の時間では790ミリ秒後に22秒に変わるはずですが、hoge()
は21時21分21秒210ミリ秒から1000ミリ秒ごとに更新されるので、hoge()
による時間表示が21時21分22秒になるのは実際の時間軸での21時21分22秒210ミリ秒の時点ということになり、210ミリ秒の誤差を生んでしまいます。
時計を標榜する以上、この誤差は致命的ですから、
setTimeout(() => {
setInterval("hoge()",1000);
}, 1000 - new Date().getUTCMilliseconds());
として、ミリ秒を実際の時間と合うようにしました。
しかし、このままでは時計が表示されるまでにsetTimeout()
で調節した分のタイムラグが発生しますから、アニメーションで時計を1000msかけて浮き上がらせることで誤魔化して違和感のないようにしています。
背景色・文字色・フォントを変更
カラーピッカーから色を選んで時計の背景色や文字色をカスタマイズできるようにしました。
カラーピッカーは最初は<input type="color">
にしようかと思いましたが、OS依存のカラーピッカーはプラットフォームによって仕様が異なり統一感を損なうことと、個人的にあれはユーザーフレンドリーでない操作感だと思うので、代わりにこちらのライブラリを採用しました。👇
GPL-3.0 Licenseなので使い勝手がいいとは言えませんが、カラーピッカーの直感的でわかりやすいUIとマテリアルなデザインがこのアプリにとてもマッチしているように思います。
設定画面こんな感じ👇
フォントも200種類から選べるようにしています。(全てGoogle fonts)
レトロゲームっぽいものからポップなものまで、なるべく偏りすぎないように色々用意しました。
App内レビュー
ユーザーがアプリストアを開いてわざわざレビューを書きにくる時というのは、大抵アプリに不満があってそれを書きにくる時です。わざわざストアから辿って褒めちぎりに来てくれることなんてほとんどありません。なので、アプリ内でワンタップで評価できるようにしておかないと、レビューが集まらないどころか不満レビューだけが溜まっていくという最悪な状況になってしまいます。不具合報告フォームを作ってアプリへの不満をそちらに流し、いいなと思ってくれているユーザーには手軽に評価を送信できる環境を用意する。このことはアプリを作る上でもはや必須の施策と言えるでしょう。
App内レビューはCordovaプラグインを使うことで容易に実装できます。
ストアへの申請
名前を決める
アプリ名は、デジタル時計の:の部分からとって、COLONと名付けました。
ただ、アプリ名に「時計」などのキーワードが一切入っておらず、ASO的によろしくないのでストアの登録名は「COLON - シンプルでスタイリッシュなデジタル時計」としました。
ホーム画面にはCOLONと表示されます。
Appプレビュー
今回初めてAppプレビューを取り入れてみました。Appプレビューとはストアに登録するスクリーンショットの動画版です。動くのでストア内で注意を引きやすくなります。今回は画面録画を切り貼りしただけでAssistiveTouchが映ったままだったりボタンのONOFFが統一されていなかったりとお粗末な出来になっていますが、ストアでの見え方の工夫などのいい勉強になりました。これからも積極的に取り入れていきたいと思います。
よかったら使ってください!
思いつきの勢いのままにアプリを作ってみましたが、結構いい感じの時計アプリができたと思っています。シンプルでおしゃれな時計アプリ求めてます、という方いらっしゃいましたらぜひ使ってやってください!フィードバックなどもらえると泣いて喜びます!
Discussion