「Web User Interface API」の世界がやってくるかもしれない

# Native UIにおけるWebとモバイルアプリの違い
Webとモバイルアプリの大きな違いとして「Native UI」が挙げられます。Webでは、経験則、また巨人の肩に乗る的に「こうした方がいいUI」はあっても、モバイルアプリのように明確な（プラットフォームに沿った）デザインガイドラインはありません。

| Platform | ガイドライン | 
|:-----------------|:------------------|
| Web | なし |
| iOS/macOS | Human Interface Guidelines |
| Android | Material Design |

「鶏が先か、卵が先か」的な話にはなりますが、このことにより、iOS/Androidに比べて、WebはUIまわりのAPIは大変少なく、またあまり利用されません。

## AlertにおけるNative User Interface APIの違い

例えば、iOSでは、Alertは以下のようになっています（左）

![スクリーンショット 2019-05-09 23.59.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100460/5fb3cc17-27f9-4049-8385-8e421bc8be26.png)
https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/modality/

呼び出すAPIは以下の通りです。

```swift
@IBAction func dispAlert(sender: UIButton) {
    let alert: UIAlertController = UIAlertController(title: "アラートのタイトル", message: "アラートの本文", preferredStyle:  UIAlertControllerStyle.Alert)
    presentViewController(alert, animated: true, completion: nil)
}
```

私はこれをみた時思いました。「Webにだって、Alert(Confirm)はある！！」と。

```js
confirm("アラートの本文");
```

![スクリーンショット 2019-05-10 1.06.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100460/4fdb5d60-83e5-b1e0-04f2-bf8ef10a957b.png)


ただ、WebのAlert APIやConfirm APIは、iOSのようにそのままのデザインで使われることは多くありません。

多くの場合、APIを利用するのではなく、CSSでデザインされた自作AlertをJavaScriptで制御して「アラートのように」見せることになります。（モバイルデバイスではNative UIですが、PCからアクセスするとシンプルであるため）

## Camera UIにおけるNative User Interface APIの違い
Camera UIは顕著です。iOSのデフォルトのCamera UIは皆さんご存知だと思います。アプリで使う場合はAPIに引数を渡すことで様々なカスタマイズ項目があります。
ではWebではいかがでしょうか。

もちろん、モバイルで使っていれば、デバイスのデフォルトカメラを呼び出すことができます。しかし、カスタマイズしようとすると、以下の手順が必要になります。

- videoタグで、カメラから取得している映像をリアルタイムで流す
- 撮影したいタイミングでスクリーンショットを取得して、Canvasに描画
- Canvasデータを保存

videoタグと撮影ボタンまわりのUser Interfaceは0から（もしくはサードパーティのライブラリを用いて）自作することになります。

このようにWebとモバイルアプリは「Native User Interface API」という概念において大きく違いがあります。

## ここまでのまとめ
- モバイルアプリの世界では、Native UIはAPIから呼び出すもの
- WebではNative UIをAPIから呼び出すことはほとんどなかった（一応alert()などはある）

# PWAによって「Web User Interface API」が求められるようになるかもしれない
これらは今まであまり課題になってくることはありませんでした。Webはドキュメンテーションとしての役割が強く、アプリとしてみるには、キャッシュやデバイスAPIへのアクセス、ストレージへの保存などの機能面でハードルがあったためです。

しかしながら近年（といってももう結構前ですが） `Progressive Web Apps` という概念が提唱されました。

> プログレッシブウェブアプリは、デスクトップとモバイルの両方でインストール可能なアプリと同等の体験を提供し、ウェブ上で直接構築・配信される高速で信頼性の高いウェブアプリです。
> https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/?hl=ja

これが何であるか、どういうことができるかについては割愛しますが、これにより今までアプリの体験で重要視されていたNative UIがWebにも必要になってきました。
モバイルアプリUIで一般的なアクションシートはWebではどうする？カメラは？いちいちAPIを自作するの？

ということで、このAPIを補完する動きがでてきています。この記事ではIonic/Capacitorについて取り上げますが、以下のライブラリを併用することになります。

- Ionic Framework（Web ComponentsベースのモバイルUIフレームワーク）
- PWA Elements（Web ComponentsベースのPWA向けNativeUI補完）

それぞれを参照しあっているので、この記事だけですべての詳細を述べるのは難しいですが、これによって

- Camera
- Alert
- Toast

は、npmでインストールしてAPIを呼び出すだけで利用することができます。例えば先程紹介したカメラについては、以下のコードを書けば、UIがWeb Componentsで自動生成されて撮影したデータをbase64で取得することができます。

```ts
  const image = await Camera.getPhoto({
    quality: 90,
    allowEditing: true,
    resultType: CameraResultType.Uri
  });
  var imageUrl = image.webPath;
  imageElement.src = imageUrl;
```

![スクリーンショット 2019-05-10 0.45.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100460/b19c305c-cd53-f6b0-47d0-60ed37aec872.png)

Toastだと、以下のようになります。

```ts
  await Toast.show({
    text: 'Hello!'
  });
```

また、Ionic FrameworkのAPIを利用すれば、アクションシートやdatetimeピッカーなどのAPIを利用することができるようになります。

Capacitorはまだbeta版ですが、PWAに汎用的に対応するために、Webにも「User Interface API」の流れがやってくるかもしれません。

それでは、また。