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