Coller des images

Harry Theodoulou
Harry Theodoulou

Méthode moderne

Utiliser l'API Async Clipboard

Pour lire par programmation les images du presse-papiers de l'utilisateur (après un clic sur un bouton), vous pouvez utiliser la méthode read() de l'API Async Clipboard. Si l'autorisation de lecture depuis le presse-papiers n'a pas encore été accordée, l'appel à navigator.clipboard.read() la demande lors du premier appel de la méthode.

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

Navigateurs pris en charge

  • 86
  • 79
  • 13.1

Source

Méthode classique

Écouter l'événement paste

La méthode classique consiste à utiliser l'API Clipboard (synchrone) qui vous donne accès au champ clipboardData dans l'événement Document: paste. Cependant, cette méthode présente des limites, par exemple parce qu'elle est synchrone. Le fait de coller de grandes quantités de données peut bloquer la page.

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

Navigateurs pris en charge

  • 66
  • 79
  • 63
  • 13.1

Source

amélioration progressive

Pour les navigateurs qui ne prennent pas en charge l'API Async Clipboard, il est impossible d'accéder par programmation au presse-papiers de l'utilisateur (par exemple, lors d'un clic sur un bouton). Ainsi, pour accéder au presse-papiers d'un utilisateur lors d'un événement paste, vous pouvez utiliser l'API Async Clipboard et utiliser l'API Clipboard (synchrone).

Les objets ClipboardItem provenant de navigator.clipboard.read ont un champ types qui est un tableau, et les objets File provenant de event.clipboardData.files ont un champ type qui est une chaîne. Vous pouvez rechercher des images dans le presse-papiers dans chacun des champs type ou types de manière conditionnelle:

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

Complément d'informations

  • API Clipboard sur MDN
  • Déblocage de l'accès au presse-papiers sur web.dev

Démonstration

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