ウェブページをできる限りネイティブアプリっぽく魅せるテクニックまとめ 〜アップルにリジェクトされつづけるなら、ウェブアプリとストアをつくって自前で配信してしまおうという企み〜

f:id:kimizuka:20161211193503p:plain
https://kimizuka.github.io/web-app-store/example/
北斗市公式キャラクター ずーしーほっきー ©2013 北海道北斗市 を使用させていただいております。

ウェブページをできる限りネイティブアプリっぽくみせて配信するために色々研究しました。


もくじ

  1. はじめに
  2. ウェブアプリとは
  3. 今回制作したもの
  4. ネイティブアプリとの比較
  5. ストア以外での配信方法
  6. ホームアイコンの設定方法
  7. フルスクリーンでの表示方法
  8. オフラインでのアクセス
  9. プッシュ通知(断念)
  10. カメラへのアクセス
  11. GPS / 加速度センサ / ジャイロセンサ へのアクセス
  12. ランドスケープでの固定(断念)
  13. 大技(Safariから開かれたかホーム画面からひらかれたかの判定)
  14. 小技(タップした際の黒ずみ除去 / 長押しでメニューを開かない / テキスト選択不可 / スクロール不可)
  15. その他、実装の上で頑張ったところ
  16. まとめ

1. はじめに

このエントリーは Tech KAYAC Advent Calendar 2016 の12日目の記事です。

techblog.kayac.com


こんにちは。カヤックのフロントエンジニア、@ki_230 です。
普段はウェブフロントエンジニアとして勤務しているのですが、趣味でiPhoneアプリをつくったりもしています。

今年も2本アプリをつくっていたのですが、、、


全然審査を通過できない! (T_T) 


そう。全然審査を通過できないまま2016年が終わろうとしているのです。

ちなみに審査を通過できない理由は、「価値が長続きしない」とのこと。

f:id:kimizuka:20161211164605p:plain
https://developer.apple.com/app-store/review/rejections/jp/ より引用


価値が長続きしない! (T_T) 


別にアップルさんを責めたいわけじゃないんです。
なにに価値を感じるかは人それぞれなわけですから。
ただ、私が本職で無い分、凝ったアプリがつくれないんですね。
大体がウェブでも成立するようなアプリになってしまうんです。

しかし、ここで逆転の発想です。

こうなったら、ウェブアプリで実装してしまおう。と。
そして、それを配信する仕組みもつくってしまおう。と。
アップルから逃げるのは恥ではあるのだけど、役に立つであろう。と。

そう決意したところからこのプロジェクトははじまりました。


2. ウェブアプリとは

定義

一般的なウェブアプリとは、ウェブ上で動作するアプリケーションのことですが、
今回はサーバサイドをつかわずに HTML + CSS + JavaScript で動作するアプリケーションのこととします。

配信方法

iOSのSafariにはホーム画面に追加という、ウェブクリップをホーム画面に追加する機能があります。
例えば カヤックサイト をホーム画面に追加すると、、、

f:id:kimizuka:20161211165801g:plain

こんな感じです。
今回はこの機能をつかって、ユーザーにホーム画面においてもらうことを配信と呼ぶことにしましょう。


3. 今回制作したもの

  1. iOSのSafariからアクセスした際はストアっぽい見た目になる
  2. ホーム画面に追加してから開いた際はアプリっぽい見た目になる
  3. ホーム画面に登録して1度開けば、2度目以降はオフラインでも開ける

また、

  1. Androidからアクセスした場合はアプリっぽい見た目になる
  2. PCなどからアクセスした場合はQRコードが表示される

というものを比較的簡単につくれるフレームワーク風のものをつくりました。
2016年なんで、 React とか Gulp とかつかおうかともおもったんですが、
そんなに複雑なものをつくるわけじゃないので、生HTML、生JavaScriptで書きました。(CSSだけはCompassをつかいました)
オフラインでの動作を考えると、余計なライブラリを読み込ませるのは勿体無いですからね。


DEMO


北斗市公式キャラクター ずーしーほっきー ©2013 北海道北斗市 を使用させていただいております。

Safariで開いたときと、ホーム画面から開いたときで表示が全然違うものになっています。

kimizuka.github.io
※ iPhoneでご観覧ください!

f:id:kimizuka:20161211191536p:plain


リポジトリ

github.com



4. ネイティブアプリとの比較

ネイティブアプリ ウェブアプリ
ストア以外での配信
ホームアイコンの設定
フルスクリーンでの表示
オフラインでのアクセス
プッシュ通知 ×
カメラへのアクセス
GPSへのアクセス
加速度センサへのアクセス
ジャイロセンサへのアクセス
マイクへのアクセス ×
ランドスケープでの固定 ×

前提として、あたりまえのことですが、基本的にネイティブアプリの方が高性能です。
プッシュ通知アプリケーションバッジ をつかいたい場合、マイク をつかいたい場合、 横向きで固定 したい場合はネイティブアプリをつくりましょう。
最近はSafariの性能があがってきているので、簡単なカジュアルゲームぐらいだったらウェブアプリでもなんとかなります。
では、ひとつずつ解説していきましょう。



5. ストア以外での配信方法

ネイティブアプリは、開発版であれば比較的自由に配信できますが、基本的にはAppStoreでの配信しかできません。
ウェブアプリは前述の通り、Safariのホーム画面に追加によって配信するので完全に自由に配信できます。

ただし、ホーム画面に追加するという動作はあまり知られていないので、

  1. 画面下部に「ホーム画面に追加」を促すバルーンを設置
  2. ページをストアっぽくみせる

f:id:kimizuka:20161211185448p:plain
北斗市公式キャラクター ずーしーほっきー ©2013 北海道北斗市 を使用させていただいております。

今回はこの2点を工夫してみました。
また、後述しますが、ホーム画面から開かれたか否かをJavaScriptで判定して、CSSでまるっと見た目を変更しています。


6. ホームアイコンの設定方法

HTML上のメタタグで指定できます。

<link rel="apple-touch-icon-precomposed" href="画像のパス" />

もしくは、

<link rel="apple-touch-icon" href="画像のパス" />

で指定しましょう。
まだiOSがフラットデザインじゃなかった頃の名残で、僕は前者をつかっています。
(昔は後者の書き方だと光沢が自動で追加されてしまいました)

ホームアイコンの設定 DEMO


7. フルスクリーンでの表示方法

HTML上でメタタグで指定できます。

<meta name="apple-mobile-web-app-capable" content="yes" />

f:id:kimizuka:20161211172843g:plain

この際、ステータスバーの色を指定することができ、

<meta name="apple-mobile-web-app-status-bar-style" content="black">

だと、黒に、

<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

だと透明になります。(iOS10.1.1でしか確認してません)
残念ながら、ピクトを非表示にすることはできません。(black-translucentを指定して背景を白にすると見えなくはなります)

フルスクリーンでの表示 DEMO


ステータスバーの色変更 DEMO


8. オフラインでのアクセス

詳細は省略しますが、アプリケーションキャッシュをつかえばオフラインでもリソースを読み込めるようになります。
マニフェストファイルを書くだけで実現できるので楽々です。詳細はリポジトリをご確認ください。

github.com
htmlタグでマニフェストファイルのパスを指定して、

github.com
こちらのファイルを読み込んでいます。

本当はServiceWorkerをつかいたかったのですが、まだiOSには対応してないんですね。
時がきたら、ServiceWorkerとCacheAPIをつかってAndroid版もつくりたいところです。

9. プッシュ通知

PC版のSafariには実装されているのですが、iOS10の時点ではmobileSafariにはまだ実装されていないようです。
残念!

kimizuka.hatenablog.com


10. カメラへのアクセス

input要素をクリックしたとき、カメラにアクセスすることができます。

<input type="file" />

f:id:kimizuka:20161211174559g:plain

ただし、あくまでファイルのアップロードの為の機能なので、取り込んだ写真の加工程度であればCanvas等でできるのですが、取り込む前、例えばカメラ画面へのオーバーレイ等はできません。
ARアプリみたいなものはネイティブじゃないと実装できないわけですね。

カメラへのアクセス DEMO


11. その他センサへのアクセス

iOS10の時点では、GPS、加速度センサ、ジャイロセンサにはアクセスできます!
マイクにはアクセスできません。。。

GPS DEMO

https://kimizuka.github.io/gps/index.html

    navigator.geolocation.getCurrentPosition(function(evt) {
      console.log(evt);
      document.write("lat: " + evt.coords.latitude);
      document.write("<br />");
      document.write("long:" + evt.coords.longitude);
    });

加速度センサ DEMO


ジャイロセンサ DEMO


12. ランドスケープでの固定

地味に、これをやりたいがためにネイティブアプリをつくることもあります。
ウェブアプリでは実装できません。


13. 大技(Safariから開かれたかホーム画面からひらかれたかの判定)

JavaScript

navigator.standalone; // ホーム画面から開かれた場合はtrueになる

これが今回の肝です。
この値をみて表示を切り替えています。


14. 小技(タップした際の黒ずみ除去 / 長押しでメニューを開かない / テキスト選択不可 / スクロール不可)

CSS小技

* {
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  -webkit-touch-callout: none;
  -webkit-user-select: none;
}

と指定しておくと、
タップした際の黒ずみ、長押しでのメニュー呼び出し、テキスト選択というウェブらしさを打ち消すことができるのでおすすめです。

kimizuka.hatenablog.com

JavaScript小技

doc.body.addEventListener("touchmove", (evt) => {
  evt.preventDefault();
}, true);

と、touchmoveを切っておくと、ページがスクロールしなくなるので、とてもアプリっぽくなります。
当然のことながらtouchmoveを切って困る場合はやめておきましょう。


15. その他、実装の上で頑張ったところ

CSSでつくったJavaScript0行UI

See the Pen Drawer Menu made from CSS only by kimmy (@kimmy) on CodePen.

inputタグを強引にカスタムすることで、ドロワーメニューをJavaScriptを0行で実装しました。

また、アプリらしさを追求し、トグルボタンもJavaScript0行で実装したのですが、残念ながら今回はつかう場所がありませんでした。。。

See the Pen Toggle Button made from CSS only by kimmy (@kimmy) on CodePen.


ホーム画面に登録した後用のリロードボタンの設置

f:id:kimizuka:20161211185442p:plain
北斗市公式キャラクター ずーしーほっきー ©2013 北海道北斗市 を使用させていただいております。

ホーム画面に登録後、フルスクリーンにするとリロードボタンやブラウザバックなどのUIがなくなってしまいます。
過去の経験上、リロードボタンがないと開発中困ることが多かったので、リロードボタンを設置しておきました。
(DATE CLEARはローカルストレージを空にするボタンです。)
また、普通にリロードするだけだとキャッシュが消えない場合があったので、クエリにタイムスタンプをつけてリロードするようにしています。


16. まとめ

頑張ってつくりましたが、


ネイティブアプリをつくったほうが楽な気がしてきた! (T_T) 


そう。ネイティブアプリをつくったほうが楽な気がしてきました。
しかし、ネイティブアプリを実機で実行する為には 年間1万円程度払って ディベロッパーにならざる得ません。

「年間費を払いたくないけど、ホーム画面にアプリを登録したい!」という人には良い方法なのかもしれません。



いかがだったでしょうか。
明日こそ、ファイ部のエースごんちゃんによるヤバい話です!お楽しみに!