이미지 복사 방법

토마스 슈타이너
토마스 슈타이너

많은 최신 브라우저에서 PNG 및 SVG 형식으로 이미지를 클립보드에 복사할 수 있습니다. 다른 형식은 보안상의 이유로 아직 지원되지 않습니다.

현대적인 방식

Async Clipboard API 사용

Clipboard.write() 메서드는 ClipboardItem 객체의 배열을 사용하고 이미지가 클립보드에 작성되는 시점을 확인하는 프로미스를 반환합니다. Clipboard.write()는 포커스가 있는 window 객체에서만 사용할 수 있습니다.

브라우저 지원

  • 66
  • 79개
  • 13.1

소스

기존의 방식

navigator.clipboard.writeText() 사용

아직 모든 브라우저가 바이너리 데이터에 navigator.clipboard.write()를 지원하는 것은 아니지만 모두 navigator.clipboard.writeText()를 지원합니다. SVG 이미지를 복사하려면 이미지 자체를 복사하는 대신 SVG 소스 코드를 복사하면 됩니다. PNG 이미지의 경우 운이 나빠질 수 있습니다.

브라우저 지원

  • 66
  • 79개
  • 63
  • 13.1

소스

점진적 개선

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);
  }
});

추가 자료

데모

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);
  }
});