【JavaScript】テキストや画像をクリップボードにコピーする方法!Clipboard APIを使おう!

Webアプリを作っていて、

  • ボタンを押したらテキストや画像をコピーできたらいいのに…

と思ったことはありませんか?

そんなときに役立つのがClipboard APIです。

Clipboard APIを使えば、ボタンをクリックするだけでテキストや画像をクリップボードにコピーすることができます。

この記事では『Clipboard APIでテキストや画像をクリップボードにコピーする方法』について、以下の内容をサンプルコードを用いてわかりやすく解説します。

  • Clipboard APIとは?
  • テキストをクリップボードにコピーする方法
    • navigator.clipboard.writeText()メソッドを使う場合
    • navigator.clipboard.write()メソッドを使う場合
  • 画像をクリップボードにコピーする方法
    • <canvas>要素をコピーする方法
    • <img>要素をコピーする方法

Clipboard APIとは?

Clipboard API は、JavaScriptを使ってブラウザのクリップボードとやり取りできるWeb APIです。たとえば、ボタンをクリックしたときにテキストや画像をコピーしたり、貼り付けたりすることができます。

Clipboard APIでは、以下の2つのメソッドがよく使われます。

メソッド説明
navigator.clipboard.writeText()テキストをクリップボードに書き込む
navigator.clipboard.write()テキストや画像などをクリップボードに書き込む

これらはどちらも非同期処理(Promise)で動作します。

テキストをクリップボードにコピーする方法

navigator.clipboard.writeText()メソッドを用いて、テキストをコピーするサンプルコードを以下に示します。

<button id="copyText">コピーする</button>
<script>
  document.getElementById('copyText').addEventListener('click', async () => {
    try {
      await navigator.clipboard.writeText('Hello World');
      alert('クリップボードにテキストをコピーしました。');
    } catch (err) {
      alert('コピーに失敗しました: ' + err);
    }
  });
</script>

上記のサンプルコードでは、「コピーする」ボタンをクリックすると、'Hello World'という文字列がコピーされます。コピーされたテキストは、メモ帳やWordなどの他のアプリケーションに貼り付けて使うことができます。

サンプルコードの解説

navigator.clipboard.writeText()メソッドには、クリップボードにコピーしたいテキストを指定します。ここでは'Hello World'を指定しています。navigator.clipboard.writeText()メソッドは非同期処理なので、Promiseオブジェクトを返します。サンプルコードではasync関数の中でこのメソッドを使っているので、awaitを使っています。

また、awaitではなくthen()使って書くこともできます。以下にサンプルコードを示します。

<button id="copyText">コピーする</button>

<script>
  document.getElementById('copyText').addEventListener('click', () => {
    navigator.clipboard
      .writeText('Hello World')
      .then(() => {
        alert('クリップボードにテキストをコピーしました。');
      })
      .catch((err) => {
        alert('コピーに失敗しました: ' + err);
      });
  });
</script>

navigator.clipboard.write()メソッドを使う場合

先ほどはnavigator.clipboard.writeText()メソッドを使って、プレーンなテキストをコピーする方法を紹介しました。

ここでは、navigator.clipboard.write()メソッドを使って、HTML形式のリッチテキスト(太字などの装飾付きテキスト)をコピーする方法を紹介します。サンプルコードを以下に示します。

<button id="copyText">コピーする</button>

<script>
  document.getElementById('copyText').addEventListener('click', async () => {
    try {
      const blob = new Blob(['<b>太字のテキスト</b>'], { type: 'text/html' });
      const item = new ClipboardItem({ 'text/html': blob });
      await navigator.clipboard.write([item]);
      alert('クリップボードにテキストをコピーしました。');
    } catch (err) {
      alert('コピーに失敗しました: ' + err);
    }
  });
</script>

上記のサンプルコードでは、HTML形式のリッチテキスト(太字)をクリップボードにコピーしています。たとえば、コピーされたテキストをWordなどに貼り付けると、write()を使ってコピーされた太字のテキストはそのままスタイル付きの文字として反映されます。

サンプルコードの解説

new Blob(['<b>太字のテキスト</b>'], { type: 'text/html' })では<b>太字のテキスト</b>というHTML文字列をBlobオブジェクトとして作成しています。typeにMIMEタイプ('text/html')を指定することで、「これはHTMLですよ」と明示しています。

次に、new ClipboardItem({ 'text/html': blob })で先ほど作成したBlobオブジェクトを'text/html'のMIMEタイプとして指定し、ClipboardItemオブジェクトを作成しています。これで、クリップボードに書き込むための形式になります。

ClipboardItemオブジェクトをnavigator.clipboard.write()メソッドに渡すことで、HTML形式のテキストがクリップボードにコピーされます。

navigator.clipboard.writeText()プレーンなテキストしかコピーできませんが、navigator.clipboard.write()は HTML や画像などさまざまな形式のデータを扱えます。

画像をクリップボードにコピーする方法

画像をコピーするには少し工夫が必要です。以下の手順でコピーします。

  • <canvas>要素にコピーしたい画像を描画する
  • canvas.toBlob()で画像データからBlobオブジェクトを取得する
  • 取得したBlobオブジェクトからClipboardItemオブジェクトを生成してnavigator.clipboard.write()メソッドに渡すことで、画像がクリップボードにコピーされる

以下にサンプルコードを示します。

<canvas id="canvas" width="200" height="100"></canvas>
<button id="copyImage">画像をコピーする</button>

<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  ctx.fillStyle = 'skyblue';
  ctx.fillRect(0, 0, 200, 100);

  document.getElementById('copyImage').addEventListener('click', () => {
    canvas.toBlob(async (blob) => {
      try {
        const item = new ClipboardItem({ 'image/png': blob });
        await navigator.clipboard.write([item]);
        alert('クリップボードに画像をコピーしました。');
      } catch (err) {
        alert('画像のコピーに失敗しました: ' + err);
      }
    }, 'image/png');
  });
</script>

上記のサンプルコードでは、「画像をコピーする」ボタンをクリックすると、Canvas上の画像がPNG形式でクリップボードにコピーされ、Wordなど画像の貼り付けに対応したアプリケーションに画像を貼り付けることができます。

サンプルコードの解説

canvas.toBlob(callback, 'image/png')では、Canvas に描画された画像をPNG 形式のデータ(Blobオブジェクト)として非同期に取得しています。コールバック関数の中でblobオブジェクトが取得され、その中身は画像のバイナリデータになります。

次に、new ClipboardItem({ 'image/png': blob })で先ほど取得したBlobオブジェクトを'image/png'のMIMEタイプとして指定し、ClipboardItemオブジェクトを作成しています。これで、クリップボードに書き込むための形式になります。

ClipboardItemオブジェクトをnavigator.clipboard.write()メソッドに渡すことで、画像がクリップボードにコピーされます。

ただしtoBlob()コールバック形式の関数であるため、awaitは使えません。そこでnew Promise((resolve) => canvas.toBlob(resolve, 'image/png'))という書き方でPromiseでラップことで、awaitで使えるようにしたサンプルコードを以下に示します。

<canvas id="canvas" width="200" height="100"></canvas>
<button id="copyImage">画像をコピーする</button>

<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  ctx.fillStyle = 'skyblue';
  ctx.fillRect(0, 0, 200, 100);

  document.getElementById('copyImage').addEventListener('click', async () => {
    try {
      const blob = await new Promise((resolve) => canvas.toBlob(resolve, 'image/png'));
      const item = new ClipboardItem({ 'image/png': blob });
      await navigator.clipboard.write([item]);
      alert('クリップボードに画像をコピーしました。');
    } catch (err) {
      alert('画像のコピーに失敗しました: ' + err);
    }
  });
</script>

awaitを使うことでコードの流れが直列的に読みやすくなり、複数の非同期処理もシンプルに記述できます。

img要素をクリップボードにコピーする方法

<img>要素から直接Blobオブジェクトを生成することはできません。そのため、<canvas>要素に<img>要素の画像を一度描画し、それをBlobオブジェクトに変換する必要があります。

画像をクリップボードにコピーサンプルコードを以下に示します。

<img src="picture.jpg" id="picture" width="500" height="500" alt="" />
<button id="copyImage">画像をコピーする</button>

<script>
  document.getElementById('copyImage').addEventListener('click', () => {
    const img = document.getElementById('picture');

    // Canvas 要素を作成し、画像サイズに合わせる
    const canvas = document.createElement('canvas');
    canvas.width = img.naturalWidth;
    canvas.height = img.naturalHeight;

    const ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0); // <img>要素をCanvasに描画

    canvas.toBlob(async (blob) => {
      try {
        const item = new ClipboardItem({ 'image/png': blob });
        await navigator.clipboard.write([item]);
        alert('クリップボードに画像をコピーしました。');
      } catch (err) {
        alert('画像のコピーに失敗しました: ' + err);
      }
    }, 'image/png');
  });
</script>

上記のサンプルコードでは、「画像をコピーする」ボタンをクリックすると、<img>要素の画像がPNG形式でクリップボードにコピーされ、Wordなど画像の貼り付けに対応したアプリケーションに画像を貼り付けることができます。

注意点としては、画像を正しいサイズでコピーするには、Canvasの大きさを画像と同じにする必要があります。ここで重要なのが、画像の大きさをImageオブジェクトのwidthプロパティやheightプロパティではなく、naturalWidthプロパティとnaturalHeightプロパティを使って取得することです。

  • img.width / img.height: CSSやHTML属性で指定された「表示サイズ」
  • img.naturalWidth / img.naturalHeight: 画像ファイルそのものが持つ本来のピクセル数(オリジナルサイズ)

ページ上に表示されている画像のサイズと、実際の画像のサイズが同じとは限りません。表示サイズ(img.width / img.height)を基にCanvasのサイズを設定してしまうと、元の画像よりも解像度が下がって描画される可能性があります。その結果、コピーされた画像は本来より低画質になることがあります。

本記事のまとめ

この記事では『Clipboard APIでテキストや画像をクリップボードにコピーする方法』について、以下の内容を説明しました。

  • Clipboard APIとは?
  • テキストをクリップボードにコピーする方法
    • navigator.clipboard.writeText()メソッドを使う場合
    • navigator.clipboard.write()メソッドを使う場合
  • 画像をクリップボードにコピーする方法
    • <canvas>要素をコピーする方法
    • <img>要素をコピーする方法

お読み頂きありがとうございました。

スポンサーリンク