主题
控制粘贴板
介绍
控制粘贴板,无非就两种 Web API 实现
document.execCommand
navigator.clipboard
区别:
兼容性
document.execCommand
是旧的操作粘贴板API,随时可能被废弃navigator.clipboard
是用来替代document.execCommand
的,在旧版本浏览器也许不能使用
同步和异步
document.execCommand
是同步执行navigator.clipboard
是异步执行- 复制粘贴大量数据时,
document.execCommand
不友好,因为同步,可能会导致页面卡住
剪贴板权限
document.execCommand
不需要请求剪贴板权限,注意某些浏览器调用document.execCommand
需要用户先有操作,就像音频自动播放一样,要先有点击等操作,才能调用成功navigator.clipboard
需要用户受授剪贴板数据
写入获取
document.execCommand
只能写入,已经不能获取了jsdocument.execCommand('copy') // true or false document.execCommand('paste') // false,永远为 false
navigator.clipboard
在获取剪贴板权限后,可以写入获取
写入文本到粘贴板
typescript
function copyText(text: string, success?: () => void, error?: () => void) {
if (document.execCommand('copy')) {
try {
// 创建一个文本框,并把 innerHTML 换成要写入的文本
const txa = document.createElement('textarea')
txa.innerHTML = text
document.body.appendChild(txa)
// 选中文本
txa.select()
// 复制
const res = document.execCommand('copy')
// 从文档中移除
document.body.removeChild(txa)
if (res) {
success && success()
return
}
} catch(err) {
console.log(err)
error && error()
}
}
if (navigator.clipboard) {
// 直接调用API即可
navigator.clipboard.writeText(text).then(success).catch(error)
} else {
error && error()
}
}
写入图片到粘贴板
typescript
function copyImage(url: string, success?: () => void, error?: () => void) {
const img = new Image()
img.src = url
img.crossOrigin = ''
img.onerror = () => {
error && error()
}
img.onload = () => {
document.body.appendChild(img)
if (document.execCommand('copy')) {
// 使用 Selection + Range 选中图片这个 dom
const selection = window.getSelection()
if (selection) {
selection.removeAllRanges()
const range = document.createRange()
range.selectNode(img)
selection.addRange(range)
// 复制
const res = document.execCommand('copy')
document.body.removeChild(img)
// 把所有选中去掉
selection.removeAllRanges()
if (res) {
success && success()
return
}
}
}
if (navigator.clipboard) {
// navigator.clipboard 只能复制 png 类型的图片
// 所以考虑 url 可能是除 png 外的图片,需要用 canvas 转一次
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
if (ctx) {
ctx.drawImage(img, 0, 0)
document.body.removeChild(img)
canvas.toBlob((blob) => {
if (blob) {
// 调用 write,写入 blob 图片数据
navigator.clipboard.write([
new ClipboardItem({
'image/png': blob
})
]).then(success).catch(error)
} else {
error && error()
}
})
} else {
error && error()
}
} else {
error && error()
}
}
}
获取粘贴板数据
typescript
function readClipboard(success: (text: string) => void, error?: () => void) {
if (navigator.clipboard) {
navigator.clipboard.readText().then(success).catch(error)
} else {
error && error()
}
}