【发布时间】:2021-03-29 01:15:59
【问题描述】:
以下代码(改编自 here)在 Chrome 中单击按钮时成功地将图像文件写入剪贴板:
document.getElementById('copy-button').addEventListener('click', async () => {
try {
const data = await fetch('image.png')
const blob = await data.blob()
await navigator.clipboard.write(
[new ClipboardItem({[blob.type]: blob})]
)
console.log('success')
} catch (err) {
console.log(`${err.name}: ${err.message}`)
}
})
(类似的代码也适用于使用.then() 链接承诺或使用带有回调函数的.toBlob() 复制<canvas> 的内容)
但是,这在 Safari 中失败,抛出 NotAllowedError。我怀疑这与 blob 的异步制作有关,导致 Safari 认为对write() 的调用“超出了用户手势的范围(例如“单击”或“触摸”事件处理程序)”,如所述@ 987654322@,因为在await 部分期间,事件处理程序释放了控制权。
例如,以下代码在脚本首次运行时将 blob 预加载到全局变量中,并且对 write() 的调用无需等待任何其他异步代码完成执行:
let imageBlob
(async function () {
const data = await fetch('image.png')
const blob = await data.blob()
imageBlob = blob
console.log('Image loaded into memory')
})()
document.getElementById('image-button-preload').addEventListener('click', () => {
const clipItem = new ClipboardItem({[imageBlob.type]: imageBlob})
navigator.clipboard.write([clipItem]).then( () => {
console.log('success')
}, (reason) => {
console.log(reason)
})
})
但这显然并不理想,特别是如果图像数据是动态创建的(例如在画布中)。
所以,问题是:如何根据 Safari/webkit 接受的用户操作生成图像 blob 并将其写入剪贴板?(或者,这是 Safari/webkit 中的错误API 的实现)
【问题讨论】:
标签: javascript safari webkit clipboard