Show HN: 我创建了 snapDOM,以极快的速度将 DOM 节点捕获为图像
snapDOM 是一款高保真的 DOM 捕获工具,是我正在为 Zumly 开发的动画引擎的一部分。Zumly 是一个用于创建平滑的基于缩放的视图转换的框架。
它可以将任何 HTML 元素转换为可缩放的 SVG 图像,同时保留样式、字体、背景、Shadow DOM 内容、伪元素等等。
- 📸 完整 DOM 捕获
- 🎨 嵌入式样式、伪元素和字体
- 🖼️ 导出为 SVG, PNG, JPG, WebP, 或者
canvas
- ⚡ 轻量级,无依赖
- 📦 100% 基于标准 Web APIs
安装
您可以通过 NPM, CDN, script tag, 或者通过 importing it as a module 来使用 snapDOM。
NPM / Yarn
npm i @zumer/snapdom
yarn add @zumer/snapdom
CDN
<script src="https://unpkg.com/@zumer/snapdom@latest/dist/snapdom.min.js"></script>
Script tag (local)
<script src="snapdom.js"></script>
全局对象 snapdom
将可用。
ES Module
import { snapdom } from './snapdom.mjs';
Script Tag (Type Module)
<script type="module">
import { snapdom } from 'https://unpkg.com/@zumer/snapdom@latest/dist/snapdom.mjs';
</script>
现在您可以直接在您的 JavaScript 中调用 snapdom(el)
, snapdom.toPng(el)
等方法。
基本用法
// Capture an element as SVG Data URL
const svgDataUrl = await snapdom(document.querySelector("#myElement"));
// Insert the captured image into the page
const img = new Image();
img.src = svgDataUrl;
document.body.appendChild(img);
API
主要的 API 通过 snapdom
暴露,并提供多种捕获方法:
Method | Description | Returns
---|---|---
snapdom(el, scale?)
| 捕获为 SVG Data URL | Promise<string>
snapdom.toImg(el, scale?)
| 捕获为 HTMLImageElement
(SVG) | Promise<HTMLImageElement>
snapdom.toCanvas(el, scale?)
| 捕获为 HTMLCanvasElement
| Promise<HTMLCanvasElement>
snapdom.toPng(el, scale?)
| 捕获为 PNG 图像 (Image
) | Promise<HTMLImageElement>
snapdom.toJpg(el, scale?, quality?)
| 捕获为 JPG 图像 (Image
) | Promise<HTMLImageElement>
snapdom.toWebp(el, scale?, quality?)
| 捕获为 WebP 图像 (Image
) | Promise<HTMLImageElement>
snapdom.toBlob(el, scale?)
| 捕获为 SVG Blob
| Promise<Blob>
参数:
el
: 要捕获的 DOM 元素。scale
: 缩放因子(默认为1
)。quality
: JPG/WebP 的压缩质量(范围0
–1
)。
特殊功能
- Shadow DOM: 捕获 Web Components 和
shadowRoot
中的内容。 - Pseudo-elements: 捕获
::before
和::after
,包括背景图像。 - Backgrounds and images: 将外部图像内联为 Data URLs。
- Fonts: 复制应用的字体系列,而无需外部字体文件。
- Placeholder and Exclusion:
data-capture="exclude"
: 跳过一个元素,同时保留布局空间。data-capture="placeholder"
+data-placeholder-text="Text"
: 用装饰性的占位符文本替换一个元素。
完整示例
<div id="captureMe">
<h1 style="color: tomato;">Hello World!</h1>
<p>This content will be captured.</p>
</div>
<script type="module">
import { snapdom } from './snapdom.esm.js';
const button = document.createElement('button');
button.textContent = "Capture";
button.onclick = async () => {
const img = await snapdom.toPng(document.getElementById('captureMe'), 2);
document.body.appendChild(img);
};
document.body.appendChild(button);
</script>
局限性
- 外部图像必须是 CORS 可访问的。
- 字体必须在捕获之前完全加载(自动等待
document.fonts.ready
)。 - Iframes 不会被捕获。
基准测试
snapDOM
不仅高度准确,而且在捕获大型或复杂的 DOM 结构时也 非常快。
在针对流行库的基准测试中:
Element Size | Winner | Compared to modern-screenshot
| Compared to html2canvas
---|---|---|---
200×100 (Small) | modern-screenshot
| 1.18× faster | 4.46× faster
400×300 (Modal) | snapDOM
| 1.04× faster | 4.07× faster
1200×800 (Page view) | snapDOM
| 2.43× faster | 5.74× faster
2000×1500 (Large scroll area) | snapDOM
| 5.02× faster | 9.35× faster
4000×2000 (Very large) | snapDOM
| 11.35× faster | 15.98× faster
✅ 关键发现:虽然 modern-screenshot
对于非常小的元素来说仍然稍快一些,但 随着 DOM 大小的增加,snapDOM 显著优于所有其他元素。
✅ 非常适合:
- 捕获全页视图
- 捕获模态窗口
- 具有自定义字体、背景或 Shadow DOM 的复杂布局
许可证
MIT © Juan Martín Muda - Zumerlab
snapDOM captures DOM nodes as images with exceptional speed avoiding bottlenecks and long tasks.