Nhiều trình duyệt hiện đại hỗ trợ việc sao chép hình ảnh vào bảng nhớ tạm ở định dạng PNG và SVG. Vì lý do bảo mật, các định dạng khác hiện chưa được hỗ trợ.
Cách làm hiện đại
Sử dụng Async Clipboard API
Phương thức Clipboard.write() lấy một mảng các đối tượng ClipboardItem và trả về một Promise phân giải khi hình ảnh được ghi thành công vào bảng nhớ tạm. Clipboard.write() chỉ có thể được dùng từ đối tượng window có tiêu điểm.
Cách cổ điển
Sử dụng navigator.clipboard.writeText()
Mặc dù chưa phải trình duyệt nào cũng hỗ trợ navigator.clipboard.write() cho dữ liệu nhị phân, nhưng tất cả đều hỗ trợ navigator.clipboard.writeText(). Nếu muốn sao chép hình ảnh SVG, thay vì sao chép chính hình ảnh đó, bạn có thể sao chép mã nguồn SVG. Rất tiếc, bạn không thể làm được điều này đối với hình ảnh PNG.
Cải tiến tăng dần
const button = document.querySelector('button');
const img = document.querySelector('img');
button.addEventListener('click', async () => {
const responsePromise = fetch(img.src);
try {
if ('write' in navigator.clipboard) {
await navigator.clipboard.write([
new ClipboardItem({
'image/svg+xml': new Promise(async (resolve) => {
const blob = await responsePromise.then(response => response.blob());
resolve(blob);
}),
}),
]);
// Image copied as image.
} else {
const text = await responsePromise.then(response => response.text());
await navigator.clipboard.writeText(text);
// Image copied as source code.
}
} catch (err) {
console.error(err.name, err.message);
}
});
Tài liệu đọc thêm
Bản minh hoạ
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 copy images</title>
</head>
<body>
<h1>How to copy images</h1>
<img src="assets/fugu.svg" alt="Fugu fish." width="128" height="128">
<button type="button">Copy</button>
</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
const button = document.querySelector('button');
const img = document.querySelector('img');
button.addEventListener('click', async () => {
const responsePromise = fetch(img.src);
try {
if ('write' in navigator.clipboard) {
await navigator.clipboard.write([
new ClipboardItem({
'image/svg+xml': new Promise(async (resolve) => {
const blob = await responsePromise.then(response => response.blob());
resolve(blob);
}),
}),
]);
// Image copied as image.
} else {
const text = await responsePromise.then(response => response.text());
await navigator.clipboard.writeText(text);
// Image copied as source code.
}
} catch (err) {
console.error(err.name, err.message);
}
});