🌐

Web Share API Level2で画像付き共有

2021/08/12に公開

概要

JavaScriptでWeb Share APIを使用すると、何かしらのテキストやURLを、ユーザーが任意のアプリケーションで共有できる機能を呼び出す事ができます。

(Web Share API 呼び出し例 左:Android 右:iPhone)

Android Chrome等、一部のブラウザではWeb Share API Level 2と呼ばれる機能が実装されており、API呼び出し時に画像も共有できるようになります。
アプリ連携などをしなくても画像付きツイートができたりするのでなかなか便利です。

本記事では、このWeb Share API Level 2を使用して画像付きの共有機能を呼び出す手順について解説します。

実行可能な環境

Web Share API自体はEdge、Safari、Chrome等のブラウザで実行可能です。
(参考:Navigator.share() - Web API | MDN)

Web Share API Level 2は、Windows Chrome、Android Chromeでのみ実行可能です。(2021-04-13時点)
(参考:Web Share API Level 2 - Chrome Platform Status)

サンプル

Web Share API Level2で画像付き共有(CodePen)

解説

処理の流れは以下の通りです。

  1. canvas要素に色々描画する
  2. canvasに描画した画素情報をDataURLに変換
  3. DataURLをBlob形式に変換
  4. BlobをFileオブジェクトに変換
  5. Web Share APIを呼び出す時の引数にFileオブジェクトを含める

canvas要素に色々描画する

html側にcanvas要素を用意して、JavaScript側で色々描画。
今回は適当に青色の矩形を描いておきます。

  <canvas id="canvas" width="320" height="240"></canvas>
  const canvas = document.getElementById("canvas");
  const context = canvas.getContext("2d");
  context.beginPath();
  context.rect(10, 10, 310, 230);
  context.fillStyle = "#0000FF";
  context.fill();
  context.closePath();

画像ファイルなどを描画したい場合は、Imageオブジェクトに読み込んだ画像を、drawImageメソッドを使ってcanvasに描いておけば良いです。以下実装例。

  const image = new Image();
  image.onload = () => {
    context.drawImage(image, 0, 0);
  };
  image.src = "何かしらの画像.png";

余談ですが、実行環境とは別のドメイン上に存在する画像をcanvasに描画すると、canvas.toDataURL実行時に "Tainted canvases may not be exported." のエラーが発生しますのでご注意ください。
(CORSの制約に引っかかります。アクセス権が適切に設定されていれば大丈夫です。)

canvasに描画した画素情報をDataURLに変換

canvasオブジェクトがDataURL変換メソッドを持っているのでそれを呼ぶだけです。

  const canvas = document.getElementById("canvas");
  const dataURL = canvas.toDataURL("image/png");

DataURLをBlob形式に変換

canvasから取得したDataURLを、atobメソッドでデコードした後、1文字ずつ取り出して配列に格納し、それをBlob形式に変換します。

  const toBlob = (base64) => {
    const decodedData = atob(base64.replace(/^.*,/, ""));
    const buffers = new Uint8Array(decodedData.length);
    for (let i = 0; i < decodedData.length; i++) {
      buffers[i] = decodedData.charCodeAt(i);
    }
    try {
      const blob = new Blob([buffers.buffer], {
        type: "image/png",
      });
      return blob;
    } catch (e) {
      return null;
    }
  };

  const blob = toBlob(dataURL);

BlobをFileオブジェクトに変換

Fileオブジェクトのインスタンス生成時の引数にBlobを設定します。

  const imageFile = new File([blob], "image.png", {
    type: "image/png",
  });

Web Share APIを呼び出す時の引数にFileオブジェクトを含める

Web Share APIを呼び出します。引数には共有したいテキスト、URL、画像ファイルを設定します。
これを実行すると、Windows ChromeやAndroid Chromeでは画像付きの共有処理が呼び出されます。
Web Share API Level 2が実装されていない環境では、画像なしの共有機能が呼び出されます。
Web Share API自体が実装されていない環境ではエラー(TypeError: navigator.share is not a function)となります。

  navigator.share({
    text: "共有テスト",
    url: "https://codepen.io/de_teiu_tkg/pen/dyWaaNP",
    files: [imageFile],
  }).then(() => {
    console.log("共有成功.");
  }).catch((error) => {
    console.log(error);
  });

以上で完了です。早くMacとかiOSのブラウザでも画像付き共有ができるようになってほしいですね。

応用例

邪魔しないでカメラ

撮影中、横から第三者の手が伸びてきて撮影の邪魔をしてくるカメラアプリです。ブラウザ上で遊べます。
Android Chromeで実行すると撮影した画像を共有できます。

参考資料

Discussion