Phong cách hiện đại
Sử dụng API Bảng nhớ tạm không đồng bộ
Để đọc hình ảnh từ bảng nhớ tạm của người dùng theo cách lập trình, tức là sau khi nhấp vào nút, bạn có thể sử dụng phương thức read()
của API Bảng nhớ tạm không đồng bộ. Nếu chưa được cấp quyền đọc từ bảng nhớ tạm, thì lệnh gọi đến navigator.clipboard.read()
sẽ yêu cầu quyền đọc trong lệnh gọi đầu tiên của phương thức đó.
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);
}
});
Cách cổ điển
Theo dõi sự kiện paste
Cách cổ điển để dán hình ảnh là sử dụng API Bảng tổng hợp (đồng bộ). API này cho phép bạn truy cập vào trường clipboardData
trong Tài liệu: sự kiện paste
. Tuy nhiên, phương pháp này có một số hạn chế, chẳng hạn như vì nó đồng bộ nên việc dán một lượng lớn dữ liệu có thể chặn trang.
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.
}
}
});
Nâng cao dần dần
Đối với các trình duyệt không hỗ trợ API Bảng nhớ tạm Async, người dùng không thể truy cập bảng nhớ tạm của người dùng theo phương thức lập trình (ví dụ: khi nhấp vào nút). Do đó, đối với việc truy cập vào bảng nhớ tạm của người dùng trên sự kiện paste
, bạn có thể sử dụng API Bảng nhớ tạm không đồng bộ hoá và sử dụng API Bảng nhớ tạm (đồng bộ).
Các đối tượng ClipboardItem
đến từ navigator.clipboard.read
có trường types
là một mảng và các đối tượng File
đến từ event.clipboardData.files
có trường type
là một chuỗi. Bạn có thể kiểm tra có điều kiện từng trường type
hoặc types
để tìm hình ảnh trong bảng nhớ tạm:
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.
}
}
}
});
Tài liệu đọc thêm
- API bảng nhớ tạm trên MDN
- Bỏ chặn quyền truy cập vào bảng nhớ tạm trên web.dev
Bản minh họa
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);
};