Nowoczesny sposób
Korzystanie z interfejsu Async Clipboard API
Aby automatycznie odczytywać obrazy ze schowka użytkownika, czyli po kliknięciu przycisku, możesz użyć metody read()
interfejsu Async Clipboard API. Jeśli uprawnienia do odczytu ze schowka nie zostały jeszcze przyznane, wywołanie metody navigator.clipboard.read()
zażąda ich przy pierwszym wywołaniu metody.
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);
}
});
Klasyczny sposób
Posłuchaj zdarzenia paste
Klasycznym sposobem wklejania obrazów jest użycie (synchronicznego) interfejsu Clipboard API, który zapewnia dostęp do pola clipboardData
w wydarzeniu Dokument: paste
. Ta metoda ma jednak pewne ograniczenia, np. dlatego, że jest synchroniczna, więc wklejenie dużej ilości danych może zablokować stronę.
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.
}
}
});
Stopniowe ulepszanie
W przypadku przeglądarek, które nie obsługują interfejsu Async Clipboard API, nie można automatycznie uzyskać dostępu do schowka użytkownika (na przykład przez kliknięcie przycisku). Aby uzyskiwać dostęp do schowka użytkownika w przypadku zdarzenia paste
, możesz użyć interfejsu Async Clipboard API i skorzystać z (synchronicznego) interfejsu Clipboard API.
Obiekty ClipboardItem
pochodzące z navigator.clipboard.read
mają pole types
, które jest tablicą, a obiekty File
z event.clipboardData.files
mają pole type
, które jest ciągiem znaków. Możesz warunkowo sprawdzać poszczególne pola type
i types
pod kątem obrazów w schowku:
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.
}
}
}
});
Więcej informacji
- Clipboard API w MDN
- Odblokowywanie dostępu do schowka na stronie web.dev
Prezentacja
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);
};