web架构师编辑器内容-HTML2Canvas 截图的原理

HTML2Canvas 截图的原理

目的:一个canvas元素,上面有绘制一系列的HTML节点

局限:canvas中没法添加具体的Html节点,它只是一张画布

通过canvas.getContext('2d')可以拿到canvas提供的2D渲染上下文,然后在里面绘制形状,文本,图象和其他对象。

文档地址:canvas

  • 矩形-fillRect()
  • 文本-fillText()
  • 图象-drawImage()

等等...

SVG来拯救我们

可缩放矢量图(Scalable Vector Graphics, SVG),是一种可用于描述二维的矢量图,基于XML的标记语言。

SVG中有一个神奇的元素称之为foreignObject

  • 文档地址foreignObject
  • SVG中的 foreignObject元素允许包含来自不同的 XML 命名空间的元素。在浏览器的上下文中,很可能是 XHTML / HTML。
  • 注:ie不支持

解题思路:

  • 创建一个 canvas元素
  • 创建svg文件,使用 Blob构造函数
  • 将svg中的值填充 foreignObject,然后填充想要
  • 复制节点的 HTML
  • 创建 image标签,将image.src = URL.crateObjectURL(svg)
  • 在image完成读取以后,调用canvas的drawImage方法,将图片绘制到画布上
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <canvas id="canvas-image"></canvas>
  <div class="author" id="author" style="color: red;" >
    这是模仿html2canvas使用的
  </div>
  <button>点击一下</button>
</body>
<script>
const drawCanvas = () => {
  // canvas-image元素
  const canvas = document.getElementById('canvas-image')
  canvas.width = 400;
  canvas.height = 400;
  // 需要获取截图的内容
  const element = document.getElementById('author')
  const data = 
    "<svg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'>" + 
      "<foreignObject width='100%' height='100%'>" + 
        "<div xmlns='http://www.w3.org/1999/xhtml'>" + 
          element.innerHTML + 
        "</div>" + 
      "</foreignObject>" +
    "</svg>"
   // 创建svg文件
   const svg = new Blob([data], { type: "image/svg+xml;charset=utf-8"})
   // 创建一个image元素
   const url = URL.createObjectURL(svg)
   const image = new Image()
   image.src = url;
   image.addEventListener('load', () => {
    const ctx = canvas.getContext('2d')
    if(ctx) {
      ctx.drawImage(image, 0, 0)
    }
   })
}
const btn = document.querySelector('button')
btn.addEventListener('click', drawCanvas)
</script>
</html>

样式没起作用,原因是我们只添加的html,并没有添加样式,如果要做到一样,需要把样式也添加到svg中去,这就是htmlCanvas简单的原理。

内部的原理主要是根据要截图元素的节点进行遍历,根据类型进行复制,添加样式,另外就是对于不支持foreignObject,做兼容性处理。

相关推荐
web守墓人1 小时前
【gpt生成-其一】以go语言为例,详细描述一下 :语法规范BNF/EBNF形式化描述
前端·gpt·golang
pink大呲花4 小时前
使用 Axios 进行 API 请求与接口封装:打造高效稳定的前端数据交互
前端·vue.js·交互
samuel9184 小时前
uniapp通过uni.addInterceptor实现路由拦截
前端·javascript·uni-app
泯泷4 小时前
JavaScript随机数生成技术实践 | 为什么Math.random不是安全的随机算法?
前端·javascript·安全
benben0444 小时前
Unity3D仿星露谷物语开发35之锄地动画
前端·游戏·游戏引擎
WebInfra4 小时前
🔥 Midscene 重磅更新:支持 AI 驱动的 Android 自动化
android·前端·测试
八了个戒4 小时前
「数据可视化 D3系列」入门第八章:动画效果详解(让图表动起来)
开发语言·前端·javascript·数据可视化
拉不动的猪6 小时前
无缝适配 PC 和移动端‌我们要注意哪些点呢
前端·javascript·面试
酱酱们的每日掘金6 小时前
🔥 4 月精选:AICoding Cursor上新与 MCP 实战揭秘!- AI Coding 周刊第 5 期
前端·ai编程·mcp
天天扭码6 小时前
一分钟解决 | 高频面试算法题——和为 K 的子数组(前缀和)
前端·算法·面试