Come incollare le immagini

Harry Teodoulo
Harry Theodoulou

Il modo moderno

Utilizzo dell'API Async Clipboard

Per leggere le immagini dagli appunti dell'utente in modo programmatico, ovvero dopo aver fatto clic su un pulsante, puoi utilizzare il metodo read() dell'API Async Clipboard. Se non è stata ancora concessa l'autorizzazione per leggere dagli appunti, la chiamata a navigator.clipboard.read() la richiederà alla prima chiamata del metodo.

const pasteButton = document.querySelector('#paste-button');

pasteButton.addEventListener('click', async () => {
  try {
    const clipboardItems = await navigator.clipboard.read();
    for (const clipboardItem of clipboardItems) {
      const imageTypes = clipboardItem.types.find(type => type.startsWith('image/'))
      for (const imageType of imageTypes) {
        const blob = await clipboardItem.getType(imageType);
        // Do something with the image blob.
      }
    }
  } catch (err) {
    console.error(err.name, err.message);
  }
});

Supporto del browser

  • 86
  • 79
  • 13.1

Fonte

Il classico

Ascolta l'evento paste

Il modo classico per incollare le immagini è utilizzare l'API Appunti (sincrona), che consente di accedere al campo clipboardData all'interno dell'evento Documento: paste. Tuttavia, questo metodo presenta alcune limitazioni, ad esempio perché è sincrono e se si incollano grandi quantità di dati la pagina potrebbe essere bloccata.

document.addEventListener('paste', async (e) => {
  e.preventDefault();

  for (const clipboardItem of e.clipboardData.files) {
    if (clipboardItem.type.startsWith('image/')) {
      // Do something with the image file.
    }
  }
});

Supporto del browser

  • 66
  • 79
  • 63
  • 13.1

Fonte

Miglioramento progressivo

Per i browser che non supportano l'API Async Clipboard, è impossibile accedere agli appunti dell'utente in modo programmatico (ad esempio facendo clic su un pulsante). Di conseguenza, per accedere agli appunti di un utente in un evento paste, puoi utilizzare l'API Async Clipboard e ricorrere all'API (sincrona) Clipboard.

Gli oggetti ClipboardItem provenienti da navigator.clipboard.read hanno un campo types che è un array, mentre gli oggetti File provenienti da event.clipboardData.files hanno un campo type, che è una stringa. Puoi controllare in modo condizionale la presenza di immagini negli appunti in ciascuno dei campi type o types:

document.addEventListener('paste', async (e) => {
  e.preventDefault();
  const clipboardItems = typeof navigator?.clipboard?.read === 'function' ? await navigator.clipboard.read() : e.clipboardData.files;

  for (const clipboardItem of clipboardItems) {
    let blob;
    if (clipboardItem.type?.startsWith('image/')) {
      // For files from `e.clipboardData.files`.
      blob = clipboardItem
      // Do something with the blob.
    } else {
      // For files from `navigator.clipboard.read()`.
      const imageTypes = clipboardItem.types?.filter(type => type.startsWith('image/'))
      for (const imageType of imageTypes) {
        blob = await clipboardItem.getType(imageType);
        // Do something with the blob.
      }
    }
  }
});

Per approfondire

  • API Clipboard su MDN
  • Sbloccare l'accesso agli appunti su web.dev

Demo

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 paste images</title>
  </head>
  <body>
    <h1>How to paste images</h1>
    <p>Hit <kbd>⌘</kbd> + <kbd>v</kbd> (for macOS) or <kbd>ctrl</kbd> + <kbd>v</kbd>
      (for other operating systems) to paste images anywhere in this page.
    </p>
  </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


        document.addEventListener('paste', async (e) => {
  e.preventDefault();
  const clipboardItems = typeof navigator?.clipboard?.read === 'function' ? await navigator.clipboard.read() : e.clipboardData.files;

  for (const clipboardItem of clipboardItems) {
    let blob;
    if (clipboardItem.type?.startsWith('image/')) {
      // For files from `e.clipboardData.files`.
      blob = clipboardItem
      // Do something with the blob.
      appendImage(blob);
    } else {
      // For files from `navigator.clipboard.read()`.
      const imageTypes = clipboardItem.types?.filter(type => type.startsWith('image/'))
      for (const imageType of imageTypes) {
        blob = await clipboardItem.getType(imageType);
        // Do something with the blob.
        appendImage(blob);
      }
    }
  }
});

const appendImage = (blob) => {
  const img = document.createElement('img');
  img.src = URL.createObjectURL(blob);
  document.body.append(img);
};