飞书文档复制网页内容的功能, 如下:
小王思考了片刻…
要实现这个功能, 要拆分为4个步骤:
由于小王的业务只需要复制固定区域的div, 所以第一步可以忽略, 简化成:
const element = document.getElementById("target");
时间已经很晚了, 小王咳了一杯咖啡, 继续奋战. 小王苦思冥想, 要怎么把div转换成 canvas. 他琢磨:
小王这时候已经觉得很累了, 于是索性打开浏览器搜索, 结果第一页就看到了: html2canvas. 他看了一眼, github 29K stars. 他查看了一下调用api:
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
});
它正是小王需要的!
于是小王在项目中命令行输入:
npm install --save html2canvas
然后小王在业务代码中敲下了:
function copyDivToImage() {
const element = document.getElementById("target");
html2canvas(element).then(canvas => {
// canvas 拿到了, 然后呢
}
}
小王犹豫, 为什么要转成二进制图像呢, 我直接复制 base64 字符不行吗. 不过很快, 小王就意识到了, 剪贴版API 不支持base64字符串的类型. 于是他翻开 mdn 文档:
HTMLCanvasElement: toBlob() method - Web APIs | MDN (mozilla.org)
function copyDivToImage() {
const element = document.getElementById("target");
html2canvas(element).then(canvas => {
canvas.toBlob(
(blob) => {
// 复制文件到剪贴板
},
"image/jpeg", // 文件的格式
1 // 图像压缩质量 0-1
);
});
}
这一步小王已经先前看过 MDN 文档了, ClipboardItem - Web APIs | MDN (mozilla.org) 可以直接调用浏览器的 navigator api :
function copyDivToImage() {
const element = document.getElementById("target");
html2canvas(element).then(canvas => {
canvas.toBlob(
(blob) => {
// 复制文件到剪贴板
try {
await navigator.clipboard.write([
// eslint-disable-next-line no-undef
new ClipboardItem({
[blob.type]: blob
})
]);
console.log("图像已成功复制到剪��板");
} catch (err) {
console.error("无法复制图像到剪贴板", err);
}
},
"image/jpeg", // 文件的格式
1 // 图像压缩质量 0-1
);
});
}
所有代码已经就绪, 小王随即启动项目, 运行他刚刚编写好的完美的代码. 不出所料, 他遇到了挫折:
小王看到这个报错, 完全没有头绪, 幸好有多年的开发经验, 他遇到这种问题的时候并没有慌张, 内心想, “第一次跑通常这样!”. 随即他打开百度搜索, 有一个回答引起了小王的注意:
原来, 小王是在 http 环境调试的, 他修改了代理的配置, 换成了 https 环境下调试本地代码.
然而让小王没有想到的是, 程序还是没有如期运行, 小王遇到了第二个挫折:
小王崩溃了 “这是什么鬼. 明明都是按照API文档写的!”
原来, 浏览器剪贴板对 jpeg的支持不大好, 于是小王把 canvas.toBlob()
的参数改成了 "image/png”.
他再次运行代码, 他成功了: