snapdom:基于 Web API 的 DOM 捕获引擎项目

High-performance engine for capturing, modifying, and converting DOM elements into any format.

分支2Tags73
文件最后提交记录最后更新时间
2 个月前
8 天前
17 天前
13 天前
6 天前
6 天前
1 天前
7 天前
11 天前
9 天前
16 天前
6 天前
8 天前
1 个月前
16 天前
16 天前
16 天前
1 年前
16 天前
1 天前
1 天前
11 天前
1 个月前
8 天前
8 天前
1 个月前
8 天前
8 天前

Website NPM version NPM weekly downloads GitHub contributors GitHub stars GitHub forks Sponsor tinchox5 License

English | 简体中文

SnapDOM

SnapDOM 是新一代的 DOM 截图引擎,也是 html2canvasdom-to-imagehtml-to-image 的快速、现代替代方案。 它能把任意 DOM 子树连同浏览器实际渲染出的样式、字体、图片和伪元素一起打包,生成不依赖原页面的结果,再导出为 SVG、PNG、JPG、WebP、Canvas 或 Blob;还可以通过插件导出为任意自定义格式。整个引擎速度快、模块化、易扩展,而且零依赖。

📖 文档、指南与在线演示 → snapdom.dev

功能特性

完整捕获 DOM,并嵌入样式、伪元素和字体;可导出为 SVG、PNG、JPG、WebP、canvas 或 Blob。速度快、零依赖,完全基于标准 Web API。

👉 完整的技术功能清单见 FEATURES_CN.md

官网与在线演示

https://snapdom.dev

快速开始

一行代码将任意 DOM 元素导出为 PNG:

import { snapdom } from '@zumer/snapdom';

const img = await snapdom.toPng(document.querySelector('#card'));
document.body.appendChild(img);

可复用捕获(一次克隆,多次导出):

const result = await snapdom(document.querySelector('#card'));
await result.toPng();      // → HTMLImageElement
await result.toSvg();      // → SVG 图片
await result.download({ format: 'jpg', filename: 'card.jpg' });

目录

安装

NPM / Yarn(稳定版)

npm i @zumer/snapdom
yarn add @zumer/snapdom

NPM / Yarn(开发版)

@dev@latest 是独立标签,可能指向更旧的版本。选择开发版前请先检查:

npm view @zumer/snapdom dist-tags

仅当列出的版本正是你要测试的版本时,才安装 @dev

npm i @zumer/snapdom@dev
yarn add @zumer/snapdom@dev

@dev 不代表 v3 beta。v3 发布前请使用本地源码;beta 发布后,请安装公告中的明确版本或标签。

CDN(稳定版)

<!-- 压缩版 -->
<script src="https://unpkg.com/@zumer/snapdom/dist/snapdom.js"></script>

<!-- 压缩版 ES Module -->
<script type="module">
  import { snapdom } from "https://unpkg.com/@zumer/snapdom/dist/snapdom.mjs";
</script>

CDN(开发版)

<!-- 压缩版(开发版) -->
<script src="https://unpkg.com/@zumer/snapdom@dev/dist/snapdom.js"></script>

<!-- 压缩版 ES Module(开发版) -->
<script type="module">
  import { snapdom } from "https://unpkg.com/@zumer/snapdom@dev/dist/snapdom.mjs";
</script>

构建产物

变体 文件 使用场景
ESM(支持 Tree Shaking) dist/snapdom.mjs 打包工具(Vite、webpack)、import
IIFE(全局变量) dist/snapdom.js <script> 标签、传统 require

打包工具(npm):

import { snapdom } from '@zumer/snapdom';  // → dist/snapdom.mjs

<script> 标签(CDN):

<script src="https://unpkg.com/@zumer/snapdom/dist/snapdom.js"></script>
<script> snapdom.toPng(document.body).then(img => document.body.appendChild(img)); </script>

子路径导入(只使用部分功能时,打包体积更小):

import { preCache } from '@zumer/snapdom/preCache';

官方插件位于独立的包中:

npm install @zumer/snapdom-plugins
import { filter } from '@zumer/snapdom-plugins/filter';

基本用法

模式 适用场景
可复用调用 snapdom(el) 克隆一次,多次导出(如 PNG、JPG 和下载)。
快捷方法 snapdom.toPng(el) 只导出一次,代码更简洁。

可复用捕获

捕获一次,多次导出(无需重复克隆):

const el = document.querySelector('#target');
const result = await snapdom(el);

const img = await result.toPng();
document.body.appendChild(img);
await result.download({ format: 'jpg', filename: 'my-capture.jpg' });

一次性快捷方法

只需要一种格式时,可直接导出:

const png = await snapdom.toPng(el);
const blob = await snapdom.toBlob(el);
document.body.appendChild(png);

文档

完整参考文档位于 snapdom.dev/docs,会随版本同步更新,也支持站内搜索:

  • API 参考snapdom() 返回的可复用对象、快捷方法,以及各导出方法的专用选项。
  • 选项 — 逐项介绍所有捕获选项(scaledprembedFontsuseProxyexclude/filtercompressouterTransformsouterShadowscache……),并附有示例。
  • 插件 — 如何构建、注册和发布自定义插件及导出格式。社区插件见插件页面
  • 缓存与 preCache — 控制多次捕获之间的缓存,并通过 preCache 提前加载所需资源。

API 速览

snapdom(el, options?) 返回一个可复用对象(toPngtoSvgtoCanvastoBlobtoJpgtoWebpdownloadurl)。单次导出可使用快捷方法:

方法 说明
snapdom.toSvg(el, options?) 返回包含 SVG 的 HTMLImageElement
snapdom.toCanvas(el, options?) 返回 HTMLCanvasElement
snapdom.toBlob(el, options?) 返回包含 SVG 或位图数据的 Blob
snapdom.toPng(el, options?) 返回 PNG 图片
snapdom.toJpg(el, options?) 返回 JPG 图片
snapdom.toWebp(el, options?) 返回 WebP 图片
snapdom.download(el, options?) 触发下载

选项速览

所有选项均为可选,可传入 snapdom(el, options) 或任意快捷方法。

选项 类型 默认值 说明
scale number 1 输出缩放倍数
dpr number devicePixelRatio 栅格化输出的像素密度
width / height number null 目标输出尺寸(只设置一个时保持宽高比)
backgroundColor string null(JPEG/WebP 为 #ffffff 背景填充色
quality number 0.92 JPEG/WebP 质量(0–1)
format 'png' | 'jpeg' | 'webp' | 'svg' 'png' download() 使用的格式
type string 'svg' toBlob() 的 Blob 类型('png''jpeg'…)
filename string 'snapDOM' 下载文件名
embedFonts boolean false 内联 @font-face,让文字以真实字体渲染
iconFonts string | RegExp | array [] 图标字体的字体族(始终内嵌)
localFonts array [] 显式指定字体:{ family, src, weight?, style? }
excludeFonts object 按字体族 / 域名 / 子集跳过字体
exclude string[] [] 从捕获中排除的 CSS 选择器
filter (el) => boolean null 保留判断函数(返回 false 则丢弃节点)
excludeMode / filterMode 'hide' | 'remove' 'hide' 被排除节点的处理方式
clip 'viewport' | {x, y, width, height} null 只捕获指定区域,视口外内容会被裁剪
compress boolean true 将内联图片降采样到其可见分辨率
useProxy string '' 跨源图片使用的 CORS 代理前缀
fallbackURL string | fn 加载失败的 <img> 的兜底图片
cache 'soft' | 'auto' | 'full' | 'disabled' 'soft' 多次捕获之间的缓存策略
outerTransforms boolean true 在输出中保留根元素的平移/旋转
outerShadows boolean false 扩展边界以包含根元素的阴影/模糊/描边
fast boolean true 跳过空闲等待,加快捕获速度
reconcile boolean false 对照真实 DOM 测量克隆结果,把尺寸出现偏差的盒模型钉定为真实大小,可修复少见的文字重新换行/布局漂移问题,代价是捕获耗时大约翻倍 — 如果 snapdom 检测到某次捕获可能受益于此选项,会通过 console.warn 提示一次
burst boolean false 通过限定范围的 MutationObserver 对该元素的重复捕获做记忆化 — 内容未变化的重复捕获会完全跳过处理流程。未开启时,如果同一元素在 2 秒内被捕获 3 次以上,snapdom 会提示一次
invalidate boolean false 配合 burst: true 使用,为自动追踪无法感知的变化(canvas 绘制、以编程方式修改 CSSOM)强制触发一次全新捕获
plugins array 单次捕获插件(按名称覆盖全局插件)

📖 完整 API 和全部选项(附示例)→ snapdom.dev/docs

限制

  • 外部图片需要允许跨源访问;如果被跨源拦截,可使用 useProxy 选项。
  • Safari 不支持以 WebP 导出时,会回退为 PNG(已在 Safari 26.5 验证:canvas.toDataURL('image/webp') 返回 PNG)。download() 仍使用 .webp 文件名,因此保存下来的文件实际是 PNG 数据。
  • SnapDOM 对 @font-face CSS 规则的支持较完善;通过 JavaScript FontFace() 注册的字体不会被自动嵌入:请在 localFonts 选项中显式列出({ family, src }),或参阅 #43 中的解决方案。
  • Safari:启用 embedFonts,或待捕获元素包含背景图/蒙版图时,受 WebKit #219770(字体解码时机)影响,捕获速度会变慢。SnapDOM 会等待该元素实际使用的字体就绪,并校验首次 canvas 绘制是否成功,无需额外配置。
  • 自定义滚动条样式::-webkit-scrollbar):仅当元素尚未滚动时保留。元素滚动后,SnapDOM 会捕获当前视口中的内容,但不会包含滚动条。

性能基准测试

测试环境:在 Chromium 中运行仓库内的 Vitest 基准测试。实际结果可能受硬件影响。 表中数值为平均捕获耗时(毫秒),越低越好。

简单元素

场景 SnapDOM 当前版 SnapDOM v1.9.9 html2canvas html-to-image
小尺寸(200×100) 0.5 ms 0.8 ms 67.7 ms 3.1 ms
模态框(400×300) 0.5 ms 0.8 ms 75.5 ms 3.6 ms
页面视图(1200×800) 0.5 ms 0.8 ms 114.2 ms 3.3 ms
大型滚动区域(2000×1500) 0.5 ms 0.8 ms 186.3 ms 3.2 ms
超大尺寸(4000×2000) 0.5 ms 0.9 ms 425.9 ms 3.3 ms

复杂元素

场景 SnapDOM 当前版 SnapDOM v1.9.9 html2canvas html-to-image
小尺寸(200×100) 1.6 ms 3.3 ms 68.0 ms 14.3 ms
模态框(400×300) 2.9 ms 6.8 ms 87.5 ms 34.8 ms
页面视图(1200×800) 17.5 ms 50.2 ms 178.0 ms 429.0 ms
大型滚动区域(2000×1500) 54.0 ms 201.8 ms 735.2 ms 984.2 ms
超大尺寸(4000×2000) 171.4 ms 453.7 ms 1,800.4 ms 2,611.9 ms

运行基准测试

git clone https://github.com/zumerlab/snapdom.git
cd snapdom
npm install
npm run test:benchmark

开发

源码结构:

  • src/api/ — 公开 API(snapdompreCache
  • src/core/ — 捕获流程、克隆、预处理与插件
  • src/modules/ — 图片、字体、伪元素、背景与 SVG
  • src/exporters/toPngtoSvgtoBlob 等导出方法
  • dist/ — 构建产物(snapdom.jssnapdom.mjspreCache.mjsplugins.mjs

构建:

git clone https://github.com/zumerlab/snapdom.git
cd snapdom
git checkout dev
npm install
npm run compile

测试:

npx playwright install   # 浏览器测试需要
npm test
npm run test:benchmark

详细指南请参阅 CONTRIBUTING

贡献者

tinchox5 pdufour FlavioLimaMindera Jarvis2018 tarwin Amyuan23 kohaiy airamhr9 jswhisperer K1ender mosuzi 17biubiu av01d CHOYSEN pedrocateexte claude domialex stypr mon-jai puneetdixit200 RexSkz RinZ27 sharuzzaman simon1uo titoBouzout ZiuChen adajoy hjl12345

赞助者

特别感谢 @megaphonecolin@sdraper69@reynaldichernando@gamma-app@jrjohnson@ryanander 对本项目的支持!

如果你也愿意支持这个项目,可以成为赞助者

支持我们

如果 SnapDOM 帮你节省了时间,欢迎在 GitHub 上点一个 ⭐。这能让更多开发者发现它,也是我们唯一的请求。

用 SnapDOM 构建了项目?欢迎把这个徽章添加到你的 README:

Built with SnapDOM

[![Built with SnapDOM](https://img.shields.io/badge/built%20with-SnapDOM-blue)](https://snapdom.dev)

使用 SnapDOM 的项目

SnapDOM 已用于 290 多个公开仓库的生产环境(见 GitHub 依赖关系图)。以下列出部分有代表性的项目,每个项目都已通过其自身的 package.json 核实:

  • LobeHub — AI 智能体平台
  • Trilium Notes — 层级式个人知识库
  • Sealos — AI 原生云操作系统
  • Tencent tmagic-editor — 低代码页面编辑器
  • Playroom — SEEK 推出的 JSX 设计工具
  • GPT-Vis — 蚂蚁集团 AntV 推出的、面向 AI 的数据可视化工具
  • Rabby Wallet — 面向 EVM 链的浏览器钱包
  • uMap — OpenStreetMap 地图制作工具
  • ListenBrainz — MetaBrainz 推出的音乐收听记录服务
  • SnapDIFF — 浏览器内的视觉回归测试工具 (由 Zumerlab 开发)

完整案例见 snapdom.dev/made-with。如果你的项目也在使用 SnapDOM,欢迎提交 PR 添加到列表中 — 仅收录真实、可验证的项目。

许可证

MIT © Zumerlab