惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
博客园 - 司徒正美
Last Week in AI
Last Week in AI
Recent Announcements
Recent Announcements
Y
Y Combinator Blog
博客园 - 聂微东
M
MIT News - Artificial intelligence
博客园_首页
Jina AI
Jina AI
博客园 - 叶小钗
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
F
Fortinet All Blogs
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
Vercel News
Vercel News
The Cloudflare Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
N
Netflix TechBlog - Medium
B
Blog
Google DeepMind News
Google DeepMind News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 兴杰

JavaScript Library – Astro 工具 - pnpm 前端基础几何计算 – basic geometric tan sin cos CSS & JS Effect – 用 SVG 画曲线和箭头 CSS & JS Effect – 画直角三角形与边框 CSS & JS Effect – 画箭头 C# – Nullable Reference Types ASP.NET Core Library – Magick.NET CSS & JS Effect – Smooth scrollIntoView JavaScript Library – Embla Carousel DOM – checkVisibility 富文本编辑器 ProseMirror 第二篇 の Schema 富文本编辑器 ProseMirror 第一篇 の 初探 JavaScript – Pipeline Operator 工具 – Playwright 工具 – Rsbuild JavaScript Library – Markdown CSS & JS Effect – 大杂烩 OData – 大杂烩 OData – 基础语法 Basic
BOM – Clipboard API
兴杰 · 2024-11-24 · via 博客园 - 兴杰

前言

Clipboard API 就是和 copy and paste 相关的 BOM API。

Copy Text

我们经常能看见这样的交互体验

点击 Copy code 以后,下面的代码就会被 copy 起来。

等同于我们 select 那些 code 之后按 ctrl + c。

这个就是用 Clipboard API 实现的。

<button class="copy-code-btn">Copy code</button>
const copyCodeBtn = document.querySelector('.copy-code-btn')!;

copyCodeBtn.addEventListener('click', async () => {
  await window.navigator.clipboard.writeText(`console.log('hello world');`);
});

代码很简单,我就不解释了,直接看效果呗

Copy Image

除了 text 以外,想要 copy 图片也可以。

<button class="copy-image-btn">Copy image</button>
const copyImageBtn = document.querySelector('.copy-image-btn')!;

copyImageBtn.addEventListener('click', async () => {
  // 1. fetch 一张图
  const imageResponse = await fetch('/src/test-files/stooges-logo.png');
  // 2. 获取图的 blob
  const imageBlob = await imageResponse.blob();
  // 3. 把 blob 装进 ClipboardItem
  const clipboardItem = new ClipboardItem({ [imageBlob.type]: imageBlob });
  // 4. 调用 write 方法,传入 ClipboardItem
  await window.navigator.clipboard.write([clipboardItem]);
});

注1:图片必须是 png 格式,其它的格式不一定支持。

注2:只能传入一个 ClipboardItem,multiple 不一定支持。

效果

另外呢,blob 支持多种类型,比如 text/html

const htmlText = '<p>Hello, world!</p>';
const htmlTextBlob = new Blob([new TextEncoder().encode(htmlText)], {
  type: 'text/html',
});
const htmlTextClipboardItem = new ClipboardItem({ [htmlTextBlob.type]: htmlTextBlob });
await window.navigator.clipboard.write([htmlTextClipboardItem]);

这样也是 ok 的。

Paste Text

能 copy 自然也能 paste。

<button class="paste-text-btn">Paste text</button>
const pasteTextBtn = document.querySelector('.paste-text-btn')!;
pasteTextBtn.addEventListener(
'click', async () => { const text = await window.navigator.clipboard.readText(); console.log('paste: ', text); });

调用 readText 方法就可以拿到当前 copy 着的 text 了。(注:游览器会先像用户获取权限)

效果

Paste with different types

copy 的内容不仅仅是 text,也可以是图片,或者 rich text (HTML string)。

我们可以透过 read 方法读取内容,接着判断类型,然后解析出不同的内容。

pasteTextBtn.addEventListener('click', async () => {
  // 1. read items
  const clipboardItems = await window.navigator.clipboard.read();
  // 2. get first item (因为 Chrome 不支持 multiple,所以只会有 1 个 item)
  const clipboardItem = clipboardItems[0];

  // 3. 查看 item 的类型
  //    它是一个 string array
  //    假如是 html text,它会是 ['text/plain', 'text/html']
  //    假如是 html 的图片,它会是 ['text/html', 'image/png']
  console.log('types', clipboardItem.types);
  // 4. 指定读取的类型,读出来是 blob,我们还需要 decode 成 string
  const textDecoder = new TextDecoder();
  console.log('plain text', textDecoder.decode(await (await clipboardItem.getType('text/plain')).arrayBuffer()));
  console.log('html text', textDecoder.decode(await (await clipboardItem.getType('text/html')).arrayBuffer()));
});

效果

在网站 select text,最终的内容类型会是 ['text/plain', 'text/html']。

text/plain 返回的是 "Hello World" 单纯的 string。

text/html 返回的是 html string,还包括了样式。

再看看 paste image 的效果

console.log('image blob', await clipboardItem.getType('image/png'));

注:虽然图片本来是 jpeg 格式,但经过 copy paste 就变成了 png 格式,这是因为 Chrome 不支持 jpeg,只支持 png。

Copy & Paste Event

当用户在网站内 ctrl + c 或者 right click + copy 就会触发 'copy' 事件。(注:right click + copy image 在 Chrome 不会触发 copy 事件...不知道为什么🤔)

我们可以在某些 element (e.g. input, textarea, contenteditable) 或者全局 document 去监听这个事件 (copy 事件会冒泡)

document.addEventListener('copy', async (event: ClipboardEvent) => {
  console.log(await window.navigator.clipboard.readText()); // 读取 copy 的内容
  event.preventDefault(); // 阻止 copy 内容
  await window.navigator.clipboard.writeText(`can't copy this!`); // 改写 copy 的内容
});

'paste' 事件也是如此

document.addEventListener('paste', async (event: ClipboardEvent) => {
  console.log(await window.navigator.clipboard.readText()); // 读取 paste 的内容
  event.preventDefault(); // 阻止 paste 内容
});

ClipboardEvent 没有什么鸟用,主要还是操作 Clipboard API。