• 周日. 7月 3rd, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

Navigator.clipboard 获取网页图片到剪切板,然后粘贴 复制指定区域,比如一张图片

admin

11月 28, 2021

Clipboard – Web API 接口参考 | MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Clipboard

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p id="cli">https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem</p>
<img src="https://static-file.qiniu.io/www/admin/1607061731" width="128" id="test" alt="123"/>
</body>
</html>
<script>
let imgSrc = document.getElementById("test").src;
console.log(imgSrc);

async function writeClipImg(imgSrc) {
try {
const imgURL = imgSrc;
const data = await fetch(imgURL);
const blob = await data.blob();

await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
]);
console.log('Fetched image copied.');
} catch (err) {
console.error(err.name, err.message);
}
};

document.getElementById('cli').addEventListener('click', async () => {
writeClipImg(imgSrc);
})
</script>

 

注意:

1、

直接在控制台执行:
writeClipImg(imgSrc)

NotAllowedError Document is not focused.

可以通过click页面元素触发。

2、

await 
await navigator.clipboard.write

Clipboard

 

Clipboard 接口实现了 Clipboard API,如果用户授予了相应的权限,就能提供系统剪贴板的读写访问。在 Web 应用程序中,Clipboard API 可用于实现剪切、复制和粘贴功能。

系统剪贴板暴露于全局属性 Navigator.clipboard 之中。

如果用户没有适时使用 Permissions API 授予相应权限和"clipboard-read" 或 "clipboard-write" 权限,调用 Clipboard 对象的方法不会成功。

注意:实际上,现在浏览器对于访问剪贴板权限的索取各有不同,在章节 剪贴板可用性 查看更多细节。

所有剪贴板 API 方法都是异步的;它们返回一个 Promise 对象,在剪贴板访问完成后被执行。如果剪贴板访问被拒绝,promise 也会被拒绝。

剪贴板 是用于短期数据储存或转移的数据缓存区,数据转移可以发生在文档和应用程序之间。剪贴板常常实现为一个匿名的、临时的 数据缓存,有时也叫做粘贴缓存,可由绝大部分位于已定义编程接口的环境中的程序访问。

一个典型的应用程序常通过将 用户输入 如 组合键菜单选择 等映射到这些接口来访问剪贴板。

方法

Clipboard 继承自 EventTarget 接口,因此拥有它的方法。

read()
从剪贴板读取数据(比如图片),返回一个 Promise 对象。When the data has been retrieved, the promise is resolved with a DataTransfer object that provides the data。
readText()
从操作系统读取文本;returns a Promise which is resolved with a DOMString containing the clipboard’s text once it’s available。
write()
写入任意数据至操作系统剪贴板。This asynchronous operation signals that it’s finished by resolving the returned Promise
writeText()
写入文本至操作系统剪贴板。returning a Promise which is resolved once the text is fully copied into the clipboard。

剪贴板可用性

异步剪贴板 API 是一个相对较新的 API,浏览器仍在逐渐实现它。由于潜在的安全问题和技术复杂性,大多数浏览器正在逐步集成这个 API。

例如,Firefox 不支持 "clipboard-read" 和 "clipboard-write" 权限,所以使用其他方式访问或改变剪贴板中的内容会受限。

对于浏览器扩展来说,你可以要求 clipboardRead 和 clipboardWrite 权限以使用 clipboard.readText() 和 clipboard.writeText()。但基于 HTTP 的网站中包含的脚本则不能获得剪贴板对象。参考 extensions in Firefox 63

除此之外, read() 以及write() 是默认禁用且需要修改偏好设置来启用的。在使用之前请先确认浏览器兼容性表格。

规范

规范 状态 备注
Clipboard API and events
Clipboard
Working Draft Initial definition.
 
 
 
Clipboard.write() – Web API 接口参考 | MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Clipboard/write
 

Clipboard.write()

 
 

Clipboard 的方法 write() 写入图片等任意的数据到剪贴板。 这个方法可以用于实现剪切和复制的功能。

但是你要提前获取 “Permissions API” 的 "clipboard-write" 权限才能将数据写入到剪贴板。

注意: 浏览器对这个异步剪贴板的 API 仍然在讨论中。所以在使用它之前请检查 compatibility table 和 Clipboard availability in Clipboard 以获得更多的兼容性信息。

语法

var promise = navigator.clipboard.write(dataTransfer)

参数

dataTransfer
DataTransfer 对象包含了要写入剪贴板的数据。

返回值

当数据被写入到剪贴板的时候,Promise resolve 回调被执行。如果剪贴板不能完成剪贴操作,Promise  reject 回调被执行。

示例

这个例子展示了如何将当前剪贴板的内容替换为给定的内容。

function setClipboard(text) {
  let data = new DataTransfer();

  data.items.add("text/plain", text);
  navigator.clipboard.write(data).then(function() {
    /* success */
  }, function() {
    /* failure */
  });
}

代码创建了一个 DataTransfer 对象,要替换的内容存储在这里。执行 DataTransferItemList.add() (en-US) 将数据写入进去,然后执行 write() 方法,指定执行成功或错误的结果。

规范

规范 状态 备注
Clipboard API and events
write()
 
 

Navigator.clipboard – Web API 接口参考 | MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator/clipboard

Navigator.clipboard

剪贴板 Clipboard API 为 Navigator 接口添加了只读属性 clipboard,该属性返回一个可以读写剪切板内容的 Clipboard 对象。 在 Web 应用中,剪切板 API 可用于实现剪切、复制、粘贴的功能。

只有在用户事先授予网站或应用对剪切板的访问许可之后,才能使用异步剪切板读写方法。许可操作必须通过取得权限 Permissions API 的 "clipboard-read" 和/或 "clipboard-write" 项获得。

语法

theClipboard = navigator.clipboard;

用于访问系统剪切板的 Clipboard 对象。

示例

以下代码使用 navigator.clipboard 来访问系统剪切板,以读取系统剪切板的内容。

navigator.clipboard.readText().then(
  clipText => document.querySelector(".cliptext").innerText = clipText);;

这个代码片段将 HTML 中拥有类名 "cliptext" 的第一个元素的内容替换为剪切板中的内容。这段代码可用于在浏览器拓展中定时自动更新或者由事件触发,实时显示当前剪切板上的内容。

如果剪切板为空,或者不包含文本,则 "cliptext" 元素的内容将被清空。这是因为在剪切板为空或者不包含文本时,readText() 会返回一个空字符串。

标准

 
https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem

ClipboardItem

 

The ClipboardItem interface of the Clipboard API represents a single item format, used when reading or writing data via the Clipboard API. That is clipboard.read() and clipboard.write() respectively.

The benefit of having the ClipboardItem interface to represent data, is that it enables developers to cope with the varying scope of file types and data easily.

Access to the contents of the clipboard is gated behind the Permissions API: The clipboard-write permission is granted automatically to pages when they are in the active tab. The clipboard-read permission must be requested, which you can do by trying to read data from the clipboard.

Note: To work with text see the Clipboard.readText() and Clipboard.writeText() methods of the Clipboard interface.

Note: You can only pass in one clipboard item at a time.

Constructor

ClipboardItem.ClipboardItem()
Creates a new ClipboardItem object, with the MIME type as the key and Blob as the value

Properties

This interface provides the following properties.

types Read only
Returns an Array of MIME types available within the ClipboardItem.
presentationStyle Read only
Returns one of the following: "unspecified""inline" or "attachment".

Methods

This interface defines the following methods.

getType()
Returns a Promise that resolves with a Blob of the requested MIME type, or an error if the MIME type is not found.

Examples

 

Writing To Clipboard

Here we’re writing a new ClipboardItem.ClipboardItem() to the clipboard by requesting a png image using the Fetch API, and in turn, the responses' blob() method, to create the new ClipboardItem.

async function writeClipImg() {
  try {
    const imgURL = '/myimage.png';
    const data = await fetch(imgURL);
    const blob = await data.blob();

    await navigator.clipboard.write([
      new ClipboardItem({
        [blob.type]: blob
      })
    ]);
    console.log('Fetched image copied.');
  } catch(err) {
    console.error(err.name, err.message);
  }
}

Reading From The Clipboard

Here we’re returning all items on the clipboard via the clipboard.read() method. Then utilizing the ClipboardItem.types property to set the getType() argument and return the corresponding blob object.

async function getClipboardContents() {
  try {
    const clipboardItems = await navigator.clipboard.read();

    for (const clipboardItem of clipboardItems) {

      for (const type of clipboardItem.types) {
        const blob = await clipboardItem.getType(type);
        // we can now use blob here
      }

    }

  } catch (err) {
    console.error(err.name, err.message);
  }
}
 
 https://stackoverflow.com/questions/56306153/domexception-on-calling-navigator-clipboard-readtext
 
 
 Copy & Paste Images – Real-World PWA: The Making of paint.js.org – Part 3 – Thinktecture https://www.thinktecture.com/en/pwa/making-of-paint-js-copy-paste/
 
 
 
 

Interact with the clipboard

 

有两种方式可以让浏览器扩展与系统剪贴板交互: Document.execCommand() 方法以及现代的异步的 Clipboard API.

Document.execCommand() 方法常通过以下指令使用:

  • document.execCommand("copy")
  • document.execCommand("cut")
  • document.execCommand("paste")

Clipboard API 提供了异步的连接来直接读写剪贴板内容. 例, 如此从剪贴板读取文本:

navigator.clipboard.readText().then(text => outputElem.innerText = text);

这将请求剪贴板内容, 并且当接收到响应时存储剪贴板文本到一个元素的 innerText.

注意: 异步的 Clipboard API 方法是一个近期新增的规范, 并且这个规范可能不适用于所有浏览器. 请在使用前测试了每一种方法的兼容性, 以确保支持满足您的需求.

写入系统粘贴板

有两种向剪贴板写入数据的方法. 你可以使用 document.execCommand()  来触发 “剪切” 和 “复制” 行为, 这将用选择的数据覆盖剪贴板的当前内容. 另一个选项是使用 Clipboard API 的 Clipboard.writeText() 或 Clipboard.write() 方法来用指定数据覆盖剪贴板内容.

使用 execCommand()

document.execCommand()  方法的 "cut" 与 "copy" 命令可以被用于以选中素材代替剪贴板的当前内容. 这些命令无需任何特别的权限就可以使用, 如果你在一个用于用户操作的短生存期的事件处理程序中使用他们(例如, 一次点击事件).

例如,假设你有一个下面的弹出菜单页面:

<input id="input" type="text"/>
<button id="copy">Copy</button>

使 “copy”按钮能复制 “input”中的文本,代码如下:

function copy() {
  var copyText = document.querySelector("#input");
  copyText.select();
  document.execCommand("Copy");
}

document.querySelector("#copy").addEventListener("click", copy);

由于execCommand()命令在单击事件中,所以不需要特别的权限。

此外,如果用警报(alarm)替换上面的命令来触发复制事件:

function copy() {
  var copyText = document.querySelector("#input");
  copyText.select();
  document.execCommand("Copy");
}

browser.alarms.create({
  delayInMinutes: 0.1
});

browser.alarms.onAlarm.addListener(copy);

这种触发不一定成功,它取决于浏览器是否支持。Firefox浏览器就不支持该功能,你会在浏览器控制台中看到以下信息:

"document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler."

为了能够在这种情形下使用,你需要拥有”clipboardWrite”的权限( permission)。 因此,”clipboardWrite”权限能使你不通过临时事件处理程序就可以写入系统粘贴板中。

使用 Clipboard API

Clipboard API 更加灵活, 因为你不仅可以将当前选择复制到剪贴板中, 还可以直接指定要放入剪贴板的信息.

要使用 Clipboard API 需要在你的 manifest.json 文件中申请 clipboardRead 与 clipboardWrite 权限.

对于页面脚本, 需要权限 API 的 clipboard-write 权限. 你可通过 navigator.permissions.query() (en-US) 来检查这个权限:

navigator.permissions.query({name: "clipboard-write"}).then(result => {
  if (result.state == "granted" || result.state == "prompt") {
    /* write to the clipboard now */
  }
});

这个函数使用一个字符串作为输入并且用它更新剪贴板:

function updateClipboard(newClip) {
  navigator.clipboard.writeText(newClip).then(function() {
    /* clipboard successfully set */
  }, function() {
    /* clipboard write failed */
  });
}

特定浏览器注意事项

 这里涉及的剪贴板和其他API正在快速发展, 因此浏览器在工作方式上存在差异.

在Chrome中:

  • 你可以在所有执行上下文中写入系统粘贴板,像背景网页、内容脚本、标签页和弹出菜单。
  • 你不需要 "clipboardWrite" 权限,甚至不需要在用户生成的事件处理程序中写入粘贴板

在Firefox中:

  • 除了背景网页外,你可以在所有执行上下文中使用 execCommand 写入粘贴板。在Firefox中,你无法选择文本或将输入字段聚焦在后台页面中,因此无法使用 execCommand 从后台页面写入剪贴板。
  • 只有version 51以上才支持”clipboardWrite” 权限。
  • 从 version 57 开始,可以使用 clipboard.setImageData() API 将图像复制到剪贴板。
  • 在 Firefox 633 中添加了对 Clipboard API navigator.clipboard.writeText() 方法的支持。
  • 当使用一个内容脚本,Clipboard API 只可用于 HTTPS 页。解决方法是,在内容脚本和后台脚本之间使用消息传递。

读取系统粘贴板

execCommand() 方法提供了 "paste" 指令,能让你粘贴内容。你可以使用 Clipboard API 的更灵活的方法: Clipboard.read() 和 Clipboard.readText()

使用 execCommand()

首先,你需要为扩展申请 "clipboardRead" permission 。即便你在用户生成的事件处理程序 ( 例如 click (en-US) 或 keypress (en-US) ) 中使用 “paste” 指令也是如此。

假设你的HTML页面内容如下:

<input id="output" type="text"/>
<button id="paste">粘贴</button>

要在用户单机 id 为 "paste" 的 <button> 时从剪贴板设置 id 为 "output" 的 <textarea> 的内容,可以使用这样的代码:

function paste() {
  var pasteText = document.querySelector("#output");
  pasteText.focus();
  document.execCommand("paste");
  console.log(pasteText.textContent);
}

document.querySelector("#paste").addEventListener("click", paste);

使用 Clipboard API

剪贴板 API 的 navigator.clipboard.readText() 和 navigator.clipboard.read() 方法让你从剪贴板读取任意文本或二进制数据。这让你从剪贴板访问数据无需将它们粘贴至一个可编辑的元素中。

一旦你通过 Permissions API 获取了 "clipboard-read" 权限,你就可以轻松读取剪贴板:

navigator.clipboard.readText().then(clipText =>
  document.getElementById("outbox").innerText = clipText);

这个代码片段从剪贴板提取文本并且用该文本替换 ID 为 "outbox" 的元素的当前内容。

特定浏览器注意事项

Firefox 在 54 版本提供了 "clipboardRead" permission ,但是仅支持向处于 内容可编辑模式 的元素粘贴,对于内容脚本,只能在 <textarea> 工作。对于后台脚本,任何元素都可被设置为内容可编辑模式。

复制指定区域,比如一张图片
window.getSelection().removeAllRanges();
let range = document.createRange()
//img标签id
range.selectNode(document.querySelector(‘#imgId’));
window.getSelection().addRange(range);
document.execCommand(“Copy”);
window.getSelection().removeAllRanges();

 

发表评论

您的电子邮箱地址不会被公开。