Nowoczesny sposób
Korzystanie z interfejsu Async Clipboard API
Aby programowo odczytywać obrazy ze schowka użytkownika, czyli po kliknięciu przycisku, możesz użyć metody read() interfejsu Async Clipboard API. Jeśli nie przyznano jeszcze uprawnień do odczytu ze schowka, wywołanie navigator.clipboard.read() poprosi o nie 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
Nasłuchiwanie zdarzenia paste
Klasycznym sposobem wklejania obrazów jest użycie (synchronicznego) interfejsu Clipboard API, który umożliwia dostęp do pola clipboardData w zdarzeniu dokumentu: paste. Ta metoda ma jednak ograniczenia. Na przykład ze względu na to, że jest synchroniczna, wklejanie dużych 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.
}
}
});
Progresywne ulepszanie
W przeglądarkach, które nie obsługują interfejsu Async Clipboard API, nie można programowo uzyskać dostępu do schowka użytkownika (np. po kliknięciu przycisku). Aby uzyskać dostęp do schowka użytkownika w zdarzeniu paste, możesz użyć interfejsu Async Clipboard API i wrócić do (synchronicznego) interfejsu Clipboard API.
Obiekty ClipboardItem pochodzące z navigator.clipboard.read mają pole types, które jest tablicą, a obiekty File pochodzące z event.clipboardData.files mają pole type, które jest ciągiem znaków. Możesz warunkowo sprawdzić, czy w schowku znajdują się obrazy, sprawdzając każde z pól type lub 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.
}
}
}
});
Więcej informacji
- Interfejs Clipboard API w MDN
- Odblokowywanie dostępu do schowka w 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);
};