前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >飞书一键复制网页内容为图片原理

飞书一键复制网页内容为图片原理

作者头像
winty
发布2024-07-31 17:41:49
1340
发布2024-07-31 17:41:49
举报
文章被收录于专栏:前端Q

飞书文档复制网页内容的功能, 如下:

小王思考了片刻…

功能拆解:

要实现这个功能, 要拆分为4个步骤:

  1. 获得选中内容所属的 div
  2. 把选中内容的div 转换成canvas
  3. 转换canvas到二进制图像
  4. 复制二进制图像到剪贴板

由于小王的业务只需要复制固定区域的div, 所以第一步可以忽略, 简化成:

代码语言:javascript
复制



  const element = document.getElementById("target");

转换div成 canvas:

时间已经很晚了, 小王咳了一杯咖啡, 继续奋战. 小王苦思冥想, 要怎么把div转换成 canvas. 他琢磨:

  1. 递归遍历 DOM 树:
    • 会从指定的根元素开始,递归遍历整个 DOM 树。
    • 对于每个遇到的元素, 分析其样式、位置、大小等属性。
  2. 处理样式和布局:
    • 通过读取元素的 CSS 样式,如颜色、背景、边框等, 复制元素的视觉表现。
    • 它会计算元素的盒模型、定位、层叠等布局信息,以确定元素在最终图片中的位置。

小王这时候已经觉得很累了, 于是索性打开浏览器搜索, 结果第一页就看到了: html2canvas. 他看了一眼, github 29K stars. 他查看了一下调用api:

代码语言:javascript
复制



html2canvas(document.body).then(function(canvas) {
    document.body.appendChild(canvas);
});

它正是小王需要的!

于是小王在项目中命令行输入:

代码语言:javascript
复制



npm install --save html2canvas

然后小王在业务代码中敲下了:

代码语言:javascript
复制



function copyDivToImage() {
  const element = document.getElementById("target");
  html2canvas(element).then(canvas => {
	  // canvas 拿到了, 然后呢
  }
}

转换canvas到二进制图像

小王犹豫, 为什么要转成二进制图像呢, 我直接复制 base64 字符不行吗. 不过很快, 小王就意识到了, 剪贴版API 不支持base64字符串的类型. 于是他翻开 mdn 文档:

HTMLCanvasElement: toBlob() method - Web APIs | MDN (mozilla.org)

代码语言:javascript
复制




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 :

代码语言:javascript
复制




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”.

他再次运行代码, 他成功了:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端Q 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 功能拆解:
  • 转换div成 canvas:
  • 转换canvas到二进制图像
  • 复制二进制图像到剪贴板
  • 小王遇到挫折
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档