iOSのSafariにWeb Share APIが来るという話を聞いたので, 趣味で作っている「ゆかりスロット」で試してみることにした. 2月2日時点でまだiOS 12.2はリリースされていないので, Stableな環境で動かしたいならChrome 61+がインストールされたAndroid端末が必要.
実装の詳細
navigator.share
に title
, url
, text
の3つのoptionalなパラメータを渡して呼び出すと, 共有可能なアプリ一覧が載ったOSネイティブのあのシートが画面下から生えてくる. それぞれのパラメータの対応状況は共有先のアプリに依存していて, 処理されたり無視されたりする. 自分が試した限りではSlack for Androidは3つとも見てくれたけど, Twitter for Androidは text
と url
しか見てくれなかった.
function shareResult(leftEye: number, rightEye: number) { const text = leftEye === 1 && rightEye === 1 ? 'ゆかりちゃん完成!!!' : 'ゆかりスロット失敗 😥' const url = `https://yukari-slot.mizdra.net/share/${leftEye}${rightEye}` navigator .share({ title: 'ゆかりスロット', text, url, }) .then(() => console.log('shared!')) .catch((e) => console.error(e)) }
navigator.share
に渡す引数が不正の場合は TypeError
, ユーザアクション契機による呼び出しでなければ NotAllowedError
, シェア先のアプリが無い場合やユーザがシェアをキャンセルした場合は AbortError
が投げられる. ゆかりスロットでは navigator.share
がない環境やシェアに失敗した場合はは Twitter Web Intentでシェアするようfallbackしている.
function createShareData(leftEye: number, rightEye: number) { const text = leftEye === 1 && rightEye === 1 ? 'ゆかりちゃん完成!!!' : 'ゆかりスロット失敗 😥' const url = `https://yukari-slot.mizdra.net/share/${leftEye}${rightEye}` return { text, url } } function createTweetLink(text: string, url: string) { const encodedText = encodeURIComponent(text) const encodedHashtags = encodeURIComponent('ゆかりスロット') const encodedUrl = encodeURIComponent(url) // Twitter Web Intentの場合は hashtags パラメータでハッシュタグを設定する return `https://twitter.com/intent/tweet?text=${encodedText}&hashtags=${encodedHashtags}&url=${encodedUrl}` } async function share ( leftEye: number | undefined, rightEye: number | undefined, ) { const { text, url } = createShareData(leftEye, rightEye) try { await navigator // ハッシュタグを付加して共有 .share({ text: `${text} #ゆかりスロット`, url }) } catch (e) { // AbortError はユーザがシェアをキャンセルした場合の // エラーなので無視する if (e.name === 'AbortError') return // navigator.share がない環境やシェアに失敗した場合は // Twitter Web Intentにfallbackする window.open(createTweetLink(text, url)) } }
今の所雑に text
パラメータにハッシュタグを含めているのでSlackにシェアするとチャンネルへのリンクになって残念なことになっている. 真面目に実装するならTwitterにシェアするボタンとWeb Share APIを呼び出すボタンは別々にしてユーザが選択できるようにすると良さそう.
ローカルでデバッグする
Web Share APIは (現状Stableなバージョンでは) Chrome for Androidでしか動かないため, Android端末を用いてデバッグすることになる. またAPIはhttpsなホスト or localhost
にのみ提供されており, Web Share APIに対応しているブラウザであってもhttpなホスト上で navigator.share
を参照すると undefined
が返ってくる. つまり, APIをローカルでデバッグするには開発マシン上の開発サーバに対して, Android端末から localhost
ホストでアクセスする必要がある.
これはChrome Dev ToolsのPort Fowarding機能を使うと簡単に実現できる. Remote devices
タブの Settings
から以下のように開発マシンのportとモバイルデバイスのportのマッピングを指定できる.