הדרך המודרנית
שימוש ב-Async Clipboard API
כדי לקרוא תמונות מלוח העריכה של המשתמש באופן פרוגרמטי, כלומר אחרי לחיצה על לחצן, אפשר להשתמש בשיטה read() של Async Clipboard API. אם עדיין לא ניתנה הרשאה לקריאה מלוח הגזירים, הקריאה אל navigator.clipboard.read() תבקש אותה בפעם הראשונה שקוראים לשיטה.
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);
}
});
הדרך הקלאסית
האזנה לאירוע paste
הדרך הקלאסית להדבקת תמונות היא באמצעות Clipboard API (סינכרוני), שנותן לכם גישה לשדה clipboardData בתוך האירוע Document: paste. עם זאת, לשיטה הזו יש מגבלות. למשל, בגלל שהיא סינכרונית, הדבקה של כמויות גדולות של נתונים עלולה לחסום את הדף.
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.
}
}
});
שיפור הדרגתי
בדפדפנים שלא תומכים ב-Async Clipboard API, אי אפשר לגשת ללוח העריכה של המשתמש באופן פרוגרמטי (לדוגמה, בלחיצה על לחצן). לכן, כדי לגשת ללוח העריכה של משתמש באירוע paste, אפשר להשתמש ב-Async Clipboard API ולחזור ל-Clipboard API (הסינכרוני).
לאובייקטים ClipboardItem שמגיעים מ-navigator.clipboard.read יש שדה types שהוא מערך, ולאובייקטים File שמגיעים מ-event.clipboardData.files יש שדה type שהוא מחרוזת. אפשר לבדוק באופן מותנה כל אחד מ-type או 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.
}
}
}
});
קריאה נוספת
- Clipboard API ב-MDN
- ביטול החסימה של הגישה ללוח העריכה ב-web.dev
הדגמה (דמו)
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);
};