【问题标题】:How to use Clipboard API to write image to clipboard in Safari如何使用剪贴板 API 将图像写入 Safari 中的剪贴板
【发布时间】: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


    【解决方案1】:

    解决方案(对于 safari)是将 Promise 分配给您传递给 ClipboardItem 的哈希图的值,如下所示:

    document.getElementById('copy-button').addEventListener('click', async () => {
      try {
        const makeImagePromise = async () => {
          const data = await fetch('image.png')
          return await data.blob()
        }
        await navigator.clipboard.write(
          [new ClipboardItem({[blob.type]: makeImagePromise() })]
        )
        console.log('success')
      } catch (err) {
        console.log(`${err.name}:  ${err.message}`)
      }
    })
    

    这样您无需等待即可调用clipboard.write,Safari 将等待您生成图像的承诺。

    注意:其他浏览器可能不支持将 promise 传递给 ClipboardItem,因此您可能需要在执行此操作之前检查 UserAgent 中是否包含 MaciOS

    【讨论】:

      猜你喜欢
      • 2017-06-06
      • 2013-07-08
      • 2021-02-12
      • 2020-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      相关资源
      最近更新 更多