异步剪贴板 API:使用 JavaScript 访问剪贴板
长期以来,访问用户剪贴板都不是一件令人愉快的事情。我们必须使用document.execCommandAPI 才能在用户剪贴板之间复制和粘贴文本,这涉及到以下步骤:
// #1. Use an input element
const input = document.querySelector('input');
// #2. Set the input's value to the text we want to copy to clipboard
input.value = 'hello there!';
// #3. Highlight the input's value
input.select();
// #4. Copy the highlighted text
document.execCommand('copy');
该input元素可以在过程中动态创建和移除,或者设置样式使其对用户不可见。我以前使用这种方法时,总觉得它看起来很糟糕,不够优雅。幸运的是,现在有了新的 Web API,让这一切变得简单多了!
异步剪贴板 API
异步剪贴板 API使 Web 应用程序能够轻松地以编程方式读取和写入系统剪贴板。关于此 API 的几点说明:
- 可通过以下方式访问:
navigator.clipboard - 该网站需要通过 HTTPS 或 localhost 提供服务。
- 仅当页面是当前活动的浏览器标签页时才有效
现在让我们来看看与旧方法相比,它实际上有多么简单。
写入剪贴板
async function writeToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
} catch (error) {
console.error(error);
}
}
该方法返回一个对象,我们可以通过链式调用或使用/Promise来等待其解析。只需这一行简短的代码,我们就将文本写入了剪贴板!.then()asyncawait
注意:在 Firefox 中,只有在响应用户手势调用时才会将文本写入剪贴板
writeText(),否则会抛出异常。Chrome 无论用户是否执行手势都会将文本写入剪贴板。两者都允许在无需请求权限的情况下写入剪贴板。
从剪贴板读取数据
async function readFromClipboard() {
try {
const text = await navigator.clipboard.readText();
console.log(text);
} catch (error) {
console.error(error);
}
}
此方法也返回一个值Promise,并且与写入剪贴板一样简单。网站首次尝试读取剪贴板内容时,浏览器会提示用户是否允许请求者进行此操作:
注意:在 Chrome 浏览器中,当用户多次关闭剪贴板(据我观察约为 3 次)后,读取剪贴板的权限将自动被拒绝。
注意:截至撰写本文时,Firefox(版本 68)尚不支持此
readText()方法,MDN 文档指出它仅在浏览器扩展中受支持。
检查剪贴板访问权限
我们可以使用权限 API检查我们是否拥有访问剪贴板的权限:
await navigator.permissions.query({name: 'clipboard-read'});
// or 'clipboard-write' for permission to write
// sample result: {state: 'granted'}
例如,我们可以利用这个结果来显示一些用户界面,让用户知道我们是否有权限访问剪贴板。
剪贴板事件
除了允许我们轻松地读写剪贴板之外,异步剪贴板 API 还提供了剪贴板事件。我们可以通过分别监听 `copy`、`cut` 和 `paste` 事件来获知用户何时执行了与剪贴板相关的操作,例如复制、剪切copy或cut粘贴paste。
document.addEventListener('copy', event => {});
document.addEventListener('cut', event => {});
document.addEventListener('paste', event => {});
writeText()使用异步剪贴板 API(例如通过 `getClipboard()` 或 `getClipboard () `)访问剪贴板时,这些事件不会触发;readText()但调用相应的命令时会触发document.execCommand。调用 ` event.preventDefault()cancel()` 会取消操作并保持剪贴板的当前状态。
这些事件仅在页面上执行操作时触发,而在其他页面或应用程序中执行操作时不会触发。
剪贴板event对象有一个DataTransferclipboardData对象属性。这允许我们覆盖将要写入剪贴板的数据,从而使我们能够以其他格式写入数据,例如:text/html
document.addEventListener('copy', event => {
event.preventDefault();
event.clipboardData.setData('text/plain', 'COPY ME!!!');
event.clipboardData.setData('text/html', '<p>COPY ME!!!</p>');
});
这样做时,我们需要调用相应的函数event.preventDefault(),以便将自定义数据写入剪贴板,而不是原始数据。对于 `add`cut和 ` pasteadd` 事件,我们需要自行处理文档中内容的删除/插入操作。
图片支持
目前我们看到的异步剪贴板 API 版本仅支持文本读写,但看起来已经很棒了!该 API 最近新增了对图像的支持,使得通过编程方式读写图像到剪贴板变得非常容易!
注意:目前仅支持 PNG 图像,但将来会添加对其他图像格式(以及可能一般的文件格式)的支持。
将图像写入剪贴板
在将图像写入剪贴板之前,我们首先需要获取图像的Blob 对象。获取图像 Blob 对象的方法有多种:
- 请用户通过文件输入框选择图像。
fetch()来自网络的图像以斑点形式呈现(带有response.blob())- 将图像绘制到 a
canvas并调用canvas.toBlob()
一旦我们有了一个图像 blob(我们称之为imageBlob),我们需要创建一个ClipboardItem包含该图像 blob 的实例:
new ClipboardItem({ 'image/png': imageBlob})
构造ClipboardItem函数接受一个对象,该对象的键是 MIME 类型,值是实际的 blob 数据。我们可以提供多个 MIME 类型和 blob 数据对,从而使用不同的类型来表示数据。
现在我们可以使用以下代码将图像写入剪贴板navigator.clipboard.write():
async function writeToClipboard(imageBlob) {
try {
await navigator.clipboard.write([
new ClipboardItem({
'image/png': imageBlob
})
]);
} catch (error) {
console.error(error);
}
}
navigator.clipboard.write()它接受一个元素数组ClipboardItem,但截至撰写本文时,仅支持单个元素。这种情况将来很可能会改变。
从剪贴板读取图像
可以使用以下方法从剪贴板读取项目(不仅限于文本)navigator.clipboard.read():
async function readFromClipboard() {
try {
const items = await navigator.clipboard.read();
} catch (error) {
console.error(error);
}
}
它返回一个数组,ClipboardItem该数组反映了系统剪贴板的内容,尽管目前在 Chrome 中它只返回剪贴板中的最新项目。
我们可以遍历这个数组来获取每个元素。我们可以通过ClipboardItem它的items属性获取所有可用的 MIME 类型,并使用其异步方法获取特定类型的实际 blob 数据getType():
for (let item of items) {
console.log(item.types); // e.g. ['image/png']
for (let type of item.types) {
const blob = await item.getType(type);
}
}
获取到数据块后,我们就可以对其进行任何操作了。我们可以使用FileReader API将数据块转换为我们需要的格式:
const reader = new FileReader();
reader.onload = () => {
const data = reader.result;
// e.g. 'data:image/png;base64,...'
};
reader.readAsDataURL(blob);
异步剪贴板 APIwrite()及其read()方法提供了访问剪贴板的通用方法。实际上,前面讨论的 ` writeText()and`readText()方法只是它们的便捷方法,也可以使用write()`/`read()或使用类型为 `.` 的 blob 来完成text/plain。
async function writeToClipboard(text) {
try {
await navigator.clipboard.write([
new ClipboardItem({
'text/plain': new Blob([text], {type: 'text/plain'})
})
]);
} catch (error) {
console.error(error);
}
}
async function readFromClipboard() {
try {
const items = await navigator.clipboard.read();
for (let item of items) {
const data = item.getType('text/plain');
// convert `data` to string using FileReader API's
// `.readAsText(data)` method
}
} catch (error) {
console.error(error);
}
}
浏览器支持和功能检测
Chrome 66和Firefox 63中已引入支持文本的异步剪贴板 API (readText()Web 应用尚不支持)。截至撰写本文时,只有 Chrome 支持 PNG 图片,该功能在Chrome 76中推出。更多信息请参阅此浏览器兼容性表格。
navigator.clipboard我们可以通过检查是否存在,在支持功能检测的浏览器上利用此 API 。
if (navigator.clipboard) {
// Safe to use Async Clipboard API!
} else {
// Use document.execCommand() instead
}
资源
感谢阅读本文,希望您喜欢并从中有所收获。以下是更多关于异步剪贴板 API 的学习资源:
文章来源:https://dev.to/arnellebalane/async-clipboard-api-accessing-the-clipboard-using-javascript-36pb
