snapdom精准的网页内容截图JS库

snapDOM

snapDOM 是一款快速精准的 DOM 转图像捕获工具,专为基于缩放的视图过渡框架 Zumly 打造。

它可以将任何 HTML 元素捕获为可缩放的 SVG 图像,并保留样式、字体、背景图像、伪元素甚至阴影 DOM。它还支持导出为光栅图像格式和画布。

  • 📸 完整的 DOM 捕获
  • 🎨 嵌入的样式、伪元素和字体
  • 🖼️ 导出为 SVG、PNG、JPG、WebP、canvas 或 Blob
  • ⚡ 超快,无依赖项
  • 📦 100% 基于标准 Web API

安装

NPM / Yarn

sh 复制代码
npm i @zumer/snapdom
sh 复制代码
yarn add @zumer/snapdom

Then import it in your code:

js 复制代码
import { snapdom } from '@zumer/snapdom';

CDN

html 复制代码
<script src="https://cdn.jsdelivr.net/npm/@zumer/snapdom/dist/snapdom.min.js"></script>

Script tag (local)

html 复制代码
<script src="snapdom.js"></script>

ES Module

js 复制代码
import { snapdom } from './snapdom.mjs';

Module via CDN

html 复制代码
<script type="module">
  import { snapdom } from 'https://cdn.jsdelivr.net/npm/@zumer/snapdom/dist/snapdom.mjs';
</script>

基本用法

可重复使用的捕获

js 复制代码
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' });

快捷方式

js 复制代码
const el = document.querySelector('#target');
const png = await snapdom.toPng(el);
document.body.appendChild(png);

const blob = await snapdom.toBlob(el);

API

snapdom(el, options?)

返回具有可重用导出方法的对象:

js 复制代码
{
  url: string;
  toRaw(): string;
  toImg(): Promise<HTMLImageElement>;
  toCanvas(): Promise<HTMLCanvasElement>;
  toBlob(options?): Promise<Blob>;
  toPng(options?): Promise<HTMLImageElement>;
  toJpg(options?): Promise<HTMLImageElement>;
  toWebp(options?): Promise<HTMLImageElement>;
  download(options?): Promise<void>;
}

快捷方法

方法 说明
snapdom.toImg(el, options?) 返回 HTMLImageElement
snapdom.toCanvas(el, options?) 返回 Canvas
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?) 触发下载

选项

注意: 样式压缩现在始终在内部启用。compress 选项已被移除。

所有捕获方法都接受 options 对象:

选项 类型 默认值 描述
fast 布尔值 true 跳过短暂的空闲延迟以获得更快的结果
embedFonts 布尔值 false 内联非图标字体(图标字体始终启用)
localFonts 数组 [] 本地字体 { family, src, weight?, style? }
iconFonts string|RegExp|Array [] 额外的图标字体匹配器
excludeFonts 对象 {} 嵌入期间排除字体系列/域/子集
scale 数字 1 输出比例乘数
dpr 数字 devicePixelRatio 设备像素比
width 数字 - 输出宽度
height 数字 - 输出高度
backgroundColor 字符串 "#fff" JPG/WebP 的备用颜色
quality 数字 1 JPG/WebP 的质量 (0 到 1)
useProxy 字符串 '' CORS 备用的代理库
type 字符串 svg 默认 Blob 类型 (svg|png|jpg|webp)
exclude 字符串[] - 要排除的 CSS 选择器
filter 函数 - 自定义谓词 (el) => boolean
cache 字符串 "soft" 控制内部缓存:disabledsoftautofull
defaultImageUrl string | function - <img> 加载失败时的后备图片。如果提供了函数,它将接收 { width?, height?, src?, element } 参数,并且必须返回一个 URL(字符串或 Promise)。适用于占位符服务(例如 https://placehold.co/{width}x{height})。

<img> 加载失败时的后备图片

<img> 加载失败提供默认图片。您可以传递固定 URL 或回调函数,该回调函数接收测量尺寸并返回 URL(方便生成动态占位符)。

js 复制代码
// 1) Fixed URL fallback
await snapdom.toImg(element, {
  defaultImageUrl: '/images/fallback.png'
});

// 2) Dynamic placeholder via callback
await snapdom.toImg(element, {
  defaultImageUrl: ({ width = 300, height = 150 }) =>
    `https://placehold.co/${Math.round(width)}x${Math.round(height)}`
});

// 3) With proxy (if your fallback host has no CORS)
await snapdom.toImg(element, {
  defaultImageUrl: ({ width = 300, height = 150 }) =>
    `https://dummyimage.com/${Math.round(width)}x${Math.round(height)}/cccccc/666.png&text=img`,
  useProxy: 'https://corsproxy.io/?url='
});

注意:

  • 如果备用图片也加载失败,snapDOM 会将 <img> 替换为一个保留宽度/高度的占位符块。
  • 回调函数使用的宽度/高度是从原始元素(数据集、样式/属性等)中获取的(如果可用)。

尺寸(scalewidthheight

  • 如果提供了 scale,则其**优先于width/height
  • 如果仅提供了 width,则高度将按比例缩放(反之亦然)。
  • 同时提供 widthheight 会强制使用精确尺寸(可能会失真)。

跨域图片和字体(useProxy

默认情况下,snapDOM 会尝试 crossOrigin="anonymous"(对于同域,则使用 use-credentials)。如果资产被 CORS 阻止,您可以将 useProxy 设置为转发实际 src 的前缀 URL:

js 复制代码
await snapdom.toPng(el, {
  useProxy: 'your-proxy' // Example 'https://api.allorigins.win/raw?url='
});

提示

  • 保持代理快速缓存友好(重复捕获时效果更佳)。
  • 代理仅用作后备;同源和启用 CORS 的资源将跳过它。

字体

embedFonts

设置为 true 时,snapDOM 会嵌入在捕获子树中检测到的非图标 @font-face 规则。图标字体(Font Awesome、Material Icons 等)始终嵌入。

localFonts

如果您自行提供字体或拥有数据 URL,可以在此处声明它们以避免额外的 CSS 检测:

js 复制代码
await snapdom.toPng(el, {
  embedFonts: true,
  localFonts: [
    { family: 'Inter', src: '/fonts/Inter-Variable.woff2', weight: 400, style: 'normal' },
    { family: 'Inter', src: '/fonts/Inter-Italic.woff2', style: 'italic' }
  ]
});

iconFonts

添加自定义图标系列(名称或正则表达式匹配器)。适用于私有图标集:

js 复制代码
await snapdom.toPng(el, {
  iconFonts: ['MyIcons', /^(Remix|Feather) Icons?$/i]
});

excludeFonts

跳过特定的非图标字体以加快捕获速度或避免不必要的下载。

js 复制代码
await snapdom.toPng(el, {
  embedFonts: true,
  excludeFonts: {
    families: ['Noto Serif', 'SomeHeavyFont'],     // skip by family name
    domains: ['fonts.gstatic.com', 'cdn.example'], // skip by source host
    subsets: ['cyrillic-ext']                      // skip by unicode-range subset tag
  }
});

注释

  • excludeFonts 仅适用于非图标字体。图标字体始终嵌入。
  • families 的匹配不区分大小写。Hosts 根据解析后的 URL 通过子字符串进行匹配。

过滤节点:excludefilter

  • exclude:通过选择器移除。
  • filter:每个元素的高级谓词(返回 false 表示删除)。

示例:使用 display:none 过滤元素:

js 复制代码
/**
 * Example filter: skip elements with display:none
 * @param {Element} el
 * @returns {boolean} true = keep, false = exclude
 */
function filterHidden(el) {
  const cs = window.getComputedStyle(el);
  if (cs.display === 'none') return false;
  return true;
}

await snapdom.toPng(document.body, { filter: filterHidden });

Example with exclude: remove banners or tooltips by selector

js 复制代码
await snapdom.toPng(el, {
  exclude: ['.cookie-banner', '.tooltip', '[data-test="debug"]']
});

preCache() – Optional helper

预加载外部资源以避免首次捕获停顿(对大型/复杂的树有帮助)。

js 复制代码
import { preCache } from '@zumer/snapdom';

await preCache({
  root: document.body,
  embedFonts: true,
  localFonts: [{ family: 'Inter', src: '/fonts/Inter.woff2', weight: 400 }],
  useProxy: 'your-proxy'
});

缓存控制

SnapDOM 维护图像、背景、资源、样式和字体的内部缓存。
您可以使用 cache 选项控制在两次捕获之间如何清除这些缓存:

模式 描述
"disabled" 无缓存
"soft" 清除会话缓存(styleMapnodeMapstyleCache)(默认)
"auto" 最小清理:仅清除临时地图
"full" 保留所有缓存(不清除任何缓存,性能最佳)

示例:

js 复制代码
// Use minimal but fast cache
await snapdom.toPng(el, { cache: 'auto' });

// Keep everything in memory between captures
await snapdom.toPng(el, { cache: 'full' });

// Force a full cleanup on every capture
await snapdom.toPng(el, { cache: 'disabled' });

限制

  • 外部图片应支持 CORS 访问(使用 useProxy 选项处理 CORS 拒绝)
  • 在 Safari 上使用 WebP 格式时,将回退到 PNG 渲染。
  • @font-face CSS 规则已得到良好支持,但如果需要使用 JS FontFace(),请参阅此解决方法 #43

性能基准测试

设置。 Vitest 在 Chromium 上的基准测试,代码库测试。硬件可能会影响结果。
值为平均捕获时间(毫秒) → 越低越好。

简单元素

Scenario SnapDOM current SnapDOM v1.9.9 html2canvas html-to-image
Small (200×100) 0.5 ms 0.8 ms 67.7 ms 3.1 ms
Modal (400×300) 0.5 ms 0.8 ms 75.5 ms 3.6 ms
Page View (1200×800) 0.5 ms 0.8 ms 114.2 ms 3.3 ms
Large Scroll (2000×1500) 0.5 ms 0.8 ms 186.3 ms 3.2 ms
Very Large (4000×2000) 0.5 ms 0.9 ms 425.9 ms 3.3 ms

复杂元素

Scenario SnapDOM current SnapDOM v1.9.9 html2canvas html-to-image
Small (200×100) 1.6 ms 3.3 ms 68.0 ms 14.3 ms
Modal (400×300) 2.9 ms 6.8 ms 87.5 ms 34.8 ms
Page View (1200×800) 17.5 ms 50.2 ms 178.0 ms 429.0 ms
Large Scroll (2000×1500) 54.0 ms 201.8 ms 735.2 ms 984.2 ms
Very Large (4000×2000) 171.4 ms 453.7 ms 1,800.4 ms 2,611.9 ms

运行基准测试

sh 复制代码
git clone https://github.com/zumerlab/snapdom.git
cd snapdom
npm install
npm run test:benchmark

路线图

SnapDOM 未来版本的改进计划:

  • 实现插件系统
    SnapDOM 将支持外部插件来扩展或覆盖内部行为(例如自定义节点转换器、导出器或过滤器)。

  • 重构模块化架构
    内部逻辑将被拆分为更小、更集中的模块,以提高可维护性和代码重用性。

  • 将内部逻辑与全局选项分离
    函数将被重新设计,以避免直接依赖“选项”。集中式捕获上下文将提高​​清晰度、自主性和可测试性。请参阅next 分支

  • 公开缓存控制
    用户将能够手动清除图像和字体缓存,或配置自己的缓存策略。

  • 自动字体预加载
    所需字体将在捕获前自动检测并预加载,从而减少手动调用 preCache() 的需要。

  • 文档插件开发
    将提供创建和注册自定义 SnapDOM 插件的完整指南。

  • 使导出实用程序可进行树优化
    诸如 toPngtoJpgtoBlob 等导出函数将被重组为独立模块,以支持树优化和最小化构建。

有任何想法或功能请求?
欢迎在 GitHub 讨论区 分享建议或反馈。

开发

贡献或本地构建 snapDOM:

sh 复制代码
# Clone the repository
git clone https://github.com/zumerlab/snapdom.git
cd snapdom

# Switch to dev branch
git checkout dev

# Install dependencies
npm install

# Compile the library (ESM, CJS, and minified versions)
npm run compile

# Install playwright browsers (necessary for running tests)
npx playwright install

# Run tests
npm test

# Run Benchmarks
npm run test:benchmark

主入口位于 src/,输出包在 dist/ 文件夹中生成。

有关详细的贡献指南,请参阅 CONTRIBUTING

关于项目

Snapdom是一个高效的网页截图 JavaScript 库,可将网页上的任意 Dom 元素快速、精确地转化为高质量图片,并支持导出为 PNG、JPG、WebP 或 Canvas 格式,适用于网页自动化测试、生成预览图、内容保存等场景。
MIT
Javascript
6,341
205
19
2025-04-27
2025-10-11

增长趋势 - stars