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