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,做兼容性处理。

相关推荐
程序员爱钓鱼40 分钟前
Rust 切片 Slice 详解:安全访问连续数据
前端·后端·rust
alexander0683 小时前
CSS 类选择器组合
前端·css
寅时码8 小时前
React 之死·终章:一个 useRef,把闭包陷阱、依赖数组、漫天 rerender 全送走
前端·react.js·ai编程
不好听6138 小时前
HTML 事件监听机制:从 DOM Level 0 到 React 合成事件
前端·react.js·html
wordbaby8 小时前
为什么刷新页面就 404?聊聊 SPA 路由与 Nginx 的那点事
前端
不好听6138 小时前
React 核心概念:JSX、组件与数据驱动
前端·react.js
触底反弹8 小时前
🔥 React 零基础入门(中):500 行屎山代码到组件化的蜕变
前端·javascript·react.js
不好听6138 小时前
React vs Vue:两大前端框架技术选型深度对比
前端·vue.js·react.js
GuWenyue9 小时前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
GuWenyue9 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法