Skip to content

Commit 2765a41

Browse files
committed
adding custom-image-formats clipboard demo from glitch
1 parent 3b0cb90 commit 2765a41

File tree

4 files changed

+145
-0
lines changed

4 files changed

+145
-0
lines changed
20.5 KB
Binary file not shown.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<link rel="icon"
8+
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>" />
9+
<title></title>
10+
<link rel="stylesheet" href="./style.css" />
11+
<script>
12+
if (!isSecureContext) location.protocol = 'https:';
13+
</script>
14+
<script src="./script.js" type="module"></script>
15+
</head>
16+
17+
<body>
18+
<h1>Web Custom formats for the Async Clipboard API</h1>
19+
<img src="./image.avif" />
20+
Original image as image/avif
21+
<canvas></canvas>
22+
<pre></pre>
23+
<button class="copy" type="button">Copy images</button>
24+
<button disabled class="paste" type="button">Paste images</button>
25+
</body>
26+
27+
</html>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
const copyButton = document.querySelector(".copy");
2+
const pasteButton = document.querySelector(".paste");
3+
const pre = document.querySelector("pre");
4+
const canvas = document.querySelector("canvas");
5+
const ctx = canvas.getContext("2d");
6+
7+
let blobs;
8+
9+
const IMG_URL = "./image.avif";
10+
11+
const toBlob = async (type) => {
12+
return new Promise((resolve) => {
13+
canvas.toBlob((blob) => {
14+
const newImg = document.createElement("img");
15+
const blobURL = URL.createObjectURL(blob);
16+
newImg.addEventListener("load", () => {
17+
URL.revokeObjectURL(blobURL);
18+
});
19+
newImg.src = blobURL;
20+
document.body.append(newImg);
21+
document.body.append(
22+
document.createTextNode(`Re-encoded image as ${blob.type}`)
23+
);
24+
resolve(blob);
25+
}, type);
26+
});
27+
};
28+
29+
const img = document.createElement("img");
30+
img.crossOrigin = "anonymous";
31+
img.addEventListener("load", async () => {
32+
canvas.width = img.naturalWidth;
33+
canvas.height = img.naturalHeight;
34+
ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight);
35+
copyButton.style.display = "block";
36+
blobs = await Promise.all(
37+
["image/jpeg", "image/webp", "image/png"].map(toBlob)
38+
);
39+
});
40+
img.src = IMG_URL;
41+
42+
copyButton.addEventListener("click", async () => {
43+
try {
44+
const data = {};
45+
blobs.forEach((blob) => {
46+
data[`${blob.type !== "image/png" ? "web " : ""}${blob.type}`] = blob;
47+
});
48+
await navigator.clipboard.write([new window.ClipboardItem(data)]);
49+
pasteButton.style.display = "block";
50+
pasteButton.disabled = false;
51+
} catch (err) {
52+
console.error(err.name, err.message);
53+
pre.style.display = "block";
54+
pre.textContent = `${err.name}: ${err.message}`;
55+
}
56+
});
57+
58+
pasteButton.addEventListener("click", async () => {
59+
const items = await navigator.clipboard.read();
60+
for (const item of items) {
61+
console.log(item.types);
62+
for (const type of item.types) {
63+
if (!/(:?web )?image\//.test(type)) {
64+
continue;
65+
}
66+
const blob = await item.getType(type);
67+
const blobURL = URL.createObjectURL(blob);
68+
const img = document.createElement("img");
69+
img.addEventListener("load", () => {
70+
URL.revokeObjectURL(blobURL);
71+
});
72+
img.src = blobURL;
73+
document.body.append(img);
74+
document.body.append(
75+
document.createTextNode(`Pasted image as ${blob.type}`)
76+
);
77+
}
78+
}
79+
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
:root {
2+
color-scheme: dark light;
3+
}
4+
5+
html {
6+
box-sizing: border-box;
7+
}
8+
9+
*,
10+
*:before,
11+
*:after {
12+
box-sizing: inherit;
13+
}
14+
15+
body {
16+
margin: 1rem;
17+
font-family: system-ui, sans-serif;
18+
}
19+
20+
img {
21+
margin-block: 1rem;
22+
height: auto;
23+
max-width: 320px;
24+
display: block;
25+
}
26+
27+
button {
28+
margin-block: 1rem;
29+
}
30+
31+
button,
32+
canvas,
33+
pre {
34+
display: none;
35+
}
36+
37+
pre {
38+
color: red;
39+
}

0 commit comments

Comments
 (0)