web-dev-qa-db-ja.com

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

リアクションウェブアプリで作業していて、実装する必要がある機能の1つは、クリックしたときに画像をコピーすることです。そのため、ユーザーはそれを次の場所に貼り付けることができます:ペイント、ワードなど...

私はいくつかのアプローチを試しましたが、最初はこの投稿に詳述されている指示に従うことでした: https://stackoverflow.com/a/40547470/9608006

これは私が思いついたものです(containerIdは最初の子として画像要素を含むdiv要素を指します):

copyImg = (containerId) => {
const imgContainerElement = document.getElementById(containerId);
this.selectText(imgContainerElement.children[0]);
document.execCommand('copy');
window.getSelection().removeAllRanges();
alert('image copied!');
}

selectText = (element) => {
    var doc = document;
    if (doc.body.createTextRange) {
      var range = document.body.createTextRange();
      range.moveToElementText(element);
      range.select();
    } else if (window.getSelection) {
      var selection = window.getSelection();
      var range = document.createRange();
      range.selectNodeContents(element);
      selection.removeAllRanges();
      selection.addRange(range);
    }
  }

うまくいきませんでした。ここに2つ星のマークが付いたソリューションを実装してみました: https://www.tek-tips.com/viewthread.cfm?qid=833917

  function copyImg(imgId){
  var r = document.body.createControlRange();
  r.add(document.getElementById(imgId));
  r.select();
  r.execCommand("COPY");
}

ただし、createControlRange()は未定義です。

navigator.clipboard apiを使用してみましたが、pngでのみ機能し、アプリはjpgで機能します。

これを達成できるnpmライブラリを探しましたが、見つけたのはテキストコピーだけでした。 npms like:react-copy-to-clipboard

任意の助けいただければ幸いです。

編集1:

次のdw _ https://stackoverflow.com/a/59183698/9608006 手順これは私が思いついたものです:(注:npm install babel-polyfillをインストールしてApp.jsにインポートする必要がありました。非同期機能を機能させてこのエラーを渡すため:regeneratorRuntimeは定義されていません)

    copyImg = async (imgElementId) => {
    const imgElement = document.getElementById(imgElementId);
    const src = imgElement.src;
    const img = await fetch(src);
    const imgBlob = await img.blob();
    if (src.endsWith(".jpg") || src.endsWith(".jpeg")) {
      copyService.convertToPng(imgBlob);
    } else if (src.endsWith(".png")) {
      copyService.copyToClipboard(imgBlob);
    } else {
      console.error("Format unsupported");
    }
 }

convertToPng = (imgBlob) => {
    const imageUrl = window.URL.createObjectURL(imgBlob);
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    const imageEl = createImage({ src: imageUrl });
    imageEl.onload = (e) => {
        canvas.width = e.target.width;
        canvas.height = e.target.height;
        ctx.drawImage(e.target, 0, 0, e.target.width, e.target.height);
        canvas.toBlob(copyToClipboard, "image/png", 1);
    };
}

createImage = (options) => {
    options = options || {};
    const img = (Image) ? new Image() : document.createElement("img");
    if (options.src) {
        img.src = options.src;
    }
    return img;
  }

copyToClipboard = (pngBlob) => {
    try {
        navigator.clipboard.write([
            new ClipboardItem({
                [pngBlob.type]: pngBlob
            })
        ]);
        console.log("Image copied");
    } catch (error) {
        console.error(error);
    }
}

コードは画像がコピーされたメッセージに到達しますが、それでもWordに貼り付けても表示されません。別のことは私が得ることです

コンソールエラー:キャッチされていません(約束どおり)DOMException

これを試すことができます。これにHTMLDivElementを提供する必要があります。

これは一般的に特定のdivへの参照です。

<div ref={node => (this._imageRef = node)}>
 <img src=""/>
</div>

次のようにコンストラクタでこの赤を初期化できます

 constructor(props) {
    super(props);

    this._imageRef = null;
  }

この_imageRefを関数に提供する必要があります。

これですべてうまくいくはずです。

export function copyImageToClipboard(element) { // element is an ref to the div here
  const selection = window.getSelection();
  const range = document.createRange();
  const img = element.firstChild ;

  // Preserve alternate text
  const altText = img.alt;
  img.setAttribute('alt', img.src);

  range.selectNodeContents(element);
  selection.removeAllRanges();
  selection.addRange(range);

  try {
    // Security exception may be thrown by some browsers.
    return document.execCommand('copy');
  } catch (ex) {
    console.warn('Copy to clipboard failed.', ex);

    return false;
  } finally {
    img.setAttribute('alt', altText);
  }
}

注:これはIEでも機能します

0
sagar.a

navigator.clipboard.writeを使用できます

function async copyImg (src) {
   const img = await fetch(src);
   const imgBlob = await img.blob();
   try {
      navigator.clipboard.write([
        new ClipboardItem({
            'image/png': imgBlob, // change image type accordingly
        })
      ]);
    } catch (error) {
        console.error(error);
    }
}
0
Zohaib Ijaz