Cách sao chép hình ảnh

Nhiều trình duyệt hiện đại hỗ trợ việc sao chép hình ảnh vào bảng nhớ tạm ở định dạng PNG và SVG. Vì lý do bảo mật, các định dạng khác hiện chưa được hỗ trợ.

Cách làm hiện đại

Sử dụng Async Clipboard API

Phương thức Clipboard.write() lấy một mảng các đối tượng ClipboardItem và trả về một Promise phân giải khi hình ảnh được ghi thành công vào bảng nhớ tạm. Clipboard.write() chỉ có thể được dùng từ đối tượng window có tiêu điểm.

Browser Support

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 127.
  • Safari: 13.1.

Source

Cách cổ điển

Sử dụng navigator.clipboard.writeText()

Mặc dù chưa phải trình duyệt nào cũng hỗ trợ navigator.clipboard.write() cho dữ liệu nhị phân, nhưng tất cả đều hỗ trợ navigator.clipboard.writeText(). Nếu muốn sao chép hình ảnh SVG, thay vì sao chép chính hình ảnh đó, bạn có thể sao chép mã nguồn SVG. Rất tiếc, bạn không thể làm được điều này đối với hình ảnh PNG.

Browser Support

  • Chrome: 66.
  • Edge: 79.
  • Firefox: 63.
  • Safari: 13.1.

Source

Cải tiến tăng dần

const button = document.querySelector('button');
const img = document.querySelector('img');

button.addEventListener('click', async () => {
  const responsePromise = fetch(img.src);
  try {
    if ('write' in navigator.clipboard) {
      await navigator.clipboard.write([
        new ClipboardItem({
          'image/svg+xml': new Promise(async (resolve) => {
            const blob = await responsePromise.then(response => response.blob());
            resolve(blob);
          }),
        }),
      ]);
      // Image copied as image.
    } else {
      const text = await responsePromise.then(response => response.text());
      await navigator.clipboard.writeText(text);
      // Image copied as source code.
    }
  } catch (err) {
    console.error(err.name, err.message);
  }
});

Tài liệu đọc thêm

Bản minh hoạ

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      rel="icon"
      href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎉</text></svg>"
    />
    <title>How to copy images</title>
  </head>
  <body>
    <h1>How to copy images</h1>
    <img src="assets/fugu.svg" alt="Fugu fish." width="128" height="128">
    <button type="button">Copy</button>
  </body>
</html>

CSS


        :root {
  color-scheme: dark light;
}

html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin: 1rem;
  font-family: system-ui, sans-serif;
}

button {
  display: block;
}
        

JS


        const button = document.querySelector('button');
const img = document.querySelector('img');

button.addEventListener('click', async () => {
  const responsePromise = fetch(img.src);

  try {
    if ('write' in navigator.clipboard) {
      await navigator.clipboard.write([
        new ClipboardItem({
          'image/svg+xml': new Promise(async (resolve) => {
            const blob = await responsePromise.then(response => response.blob());
            resolve(blob);
          }),
        }),
      ]);
      // Image copied as image.
    } else {
      const text = await responsePromise.then(response => response.text());
      await navigator.clipboard.writeText(text);
      // Image copied as source code.
    }
  } catch (err) {
    console.error(err.name, err.message);
  }
});