dom-snap-x
v1.0.4
Published
Out-of-the-box web screenshot library: pixel-perfect page reproduction with maps, charts and other complex content fully supported
Maintainers
Readme
Dom Snap X 网页截图库
English | 中文
开箱即用的网页截图方案。像素级还原页面真实效果,地图、图表等复杂内容照常出现在截图里。
安装
npm install dom-snap-xCDN(用于快速试用):
<script src="dom-snap-x/lib/dom-snap-x.umd.js"></script>
<script>
const canvas = await DomSnapX.captureViewport()
</script>引入本包对 SSR 安全——引入阶段不会触碰任何浏览器 API;截图本身在浏览器中运行。
基础截图
import { captureViewport } from 'dom-snap-x'
const canvas = await captureViewport()高清输出
放大输出可让文字更清晰,地图页面建议使用 scale: 2。
const canvas = await captureViewport({ scale: 2 })剔除部分元素
传入不想出现在截图里的元素选择器(悬浮按钮、提示条等),页面本身不受影响。
const canvas = await captureViewport({
hideSelectors: '.float-btn, .toast'
})这些选择器在同源 iframe 内部同样生效。
含地图的页面
当页面包含由 canvas 绘制的地图时,同时传入地图元素与已捕获的地图画面,地图即可完整出现在结果里。
const canvas = await captureViewport({
scale: 2,
mapCanvas: document.querySelector('#map canvas'),
mapImageUrl: mapImageDataUrl // 单独捕获的地图画面 dataURL
})地图位于同源 iframe 内部时,使用与 iframeImages 相同的分层写法——{ 0: ... } 指向页面中的第 1 个 iframe:
const canvas = await captureViewport({
mapCanvas: { 0: iframe0.contentDocument.querySelector('#map canvas') },
mapImageUrl: { 0: iframe0MapImageDataUrl }
})截取页面中的某个元素
如果不想截整个视口,只想截某个卡片、表格或弹窗,直接传入该元素即可。
import { captureElement, captureElementSvg } from 'dom-snap-x'
// 输出 canvas,尺寸自动跟随元素外框
const canvas = await captureElement(document.querySelector('.report-card'), {
scale: 2,
background: '#fff' // 元素自身透明时的衬底颜色
})
// 输出可无损缩放的 SVG(矢量)
const svg = await captureElementSvg(document.querySelector('.report-card'))元素是隔离渲染:元素自身的样式、伪元素、主题变量、图片、图标、canvas、同源 iframe 均与视口截图同等保真;只有落在被截子树之外的祖先相关规则无法还原(如祖先在外的 .parent .child,或由 flex 父容器分配来的宽高)。
注意:元素内的 vw / vh 按真实浏览器视口换算,而不是元素自身的盒子,因此使用 2.5vw 这类流式尺寸的卡片会保持它在页面上的比例。
iframe
同源 iframe 无需任何配置——会以与页面相同的分辨率截取并精确回填。
跨域 iframe 受浏览器同源策略限制无法读取其 DOM,任何纯前端方案都无法绕过。用 iframeImages 按序号传入它们的画面:
const canvas = await captureViewport({
iframeImages: {
0: 'data:image/png;base64,...', // 页面中的第 1 个 iframe
1: { url: 'data:image/png;base64,...' } // 第 2 个(可带 width / height 指定尺寸)
}
})iframe 内再嵌 iframe 时往下多写一层——例如页面中第 1 个 iframe 内部的第 2 个 iframe:
const canvas = await captureViewport({
iframeImages: { 0: { 1: 'data:image/png;base64,...' } }
})跨域资源(图片 / 字体 / 样式表)
跨域且无 CORS 的图片、字体、样式表无法被浏览器读取,默认会被替换为占位图或跳过。可用 resourceInterceptor 接管这些资源:
const canvas = await captureViewport({
resourceInterceptor: async (url, type) => {
// type: 'image' | 'css-image' | 'stylesheet'
if (type === 'stylesheet') return (await myProxy.text(url)) // 返回 CSS 文本
return await myProxy.dataUrl(url) // 返回 dataURL(Blob 也可以)
}
})返回非空即采用;返回 null / undefined 表示不接管该资源,抛错同样视为「不接管」。
自定义尺寸
const canvas = await captureViewport({
width: 1920, // 宽
height: 1080 // 高
})输出格式
所有入口共用同一套输出格式,通过 format 选择,默认 canvas:
| format | 返回 | 说明 |
| --- | --- | --- |
| canvas(默认) | HTMLCanvasElement | 自行转成任意格式 |
| svg | string | SVG dataURL,矢量输出,可无损缩放 |
| png | string | PNG dataURL(无损) |
| jpeg | string | JPEG dataURL(有损,支持 quality) |
| webp | string | WebP dataURL(有损,支持 quality) |
| blob | Blob | PNG 格式 Blob,便于直接上传 |
const png = await captureViewport({ format: 'png', scale: 2 })
const jpg = await captureElement(el, { format: 'jpeg', quality: 0.85 })
const svg = await captureElement(el, { format: 'svg' }) // 或使用 captureElementSvg(el)
const blob = await captureViewport({ format: 'blob' })quality(0-1)仅对 jpeg / webp 生效,不传则使用浏览器默认值;传入未知格式会抛错。
svg下scale只影响结果中图标的清晰度(矢量内容本身无损放大)。
导出图片
拿到 canvas(默认格式)后,自行导出:
// PNG(无损)
const png = canvas.toDataURL('image/png')
// JPEG(更小,可控制质量)
const jpg = canvas.toDataURL('image/jpeg', 0.85)
// 下载
const a = document.createElement('a')
a.href = png
a.download = 'screenshot.png'
a.click()能力探测与回退
正式使用前先探测环境,不支持时切换到自己的回退方案。
import { canCapture, captureViewport } from 'dom-snap-x'
if (await canCapture()) {
const canvas = await captureViewport({ scale: 2 })
} else {
// 你自己的回退截图方案
}错误与告警
错误——会抛出,且提示写明要改什么:
| 情形 | 行为 |
| --- | --- |
| format 不是支持的取值 | 抛出 |
| hideSelectors 选择器语法无效 | 抛出 |
| captureElement 收到非元素,或 <html>(截整页请用 captureViewport) | 抛出 |
| 目标元素不可见(如 display: none) | 抛出 |
| 请求的输出尺寸无法产出(罕见) | 抛出 |
告警——截图仍返回可用结果,同时在控制台打印一条警告:
| 情形 | 行为 |
| --- | --- |
| 请求的 scale 超出浏览器可分配的最大尺寸 | 自动收敛到可用的最大值;导出仍然成功,只是比请求的更小 |
| 某个 iframe 无法自动截取,且未通过 iframeImages 提供画面(跨域,或嵌套层数超过支持上限) | 该区域以空白呈现 |
| 页面的某一部分无法导出 | 仍返回可用截图,该部分缺失,并打印一条告警 |
把告警理解为「图可用,但有一部分降级了」。
API 参考
Dom Snap X —— 开箱即用的网页截图库。像素级还原页面真实效果;地图、图表等复杂内容照常出现在截图里;无弹窗、无扩展、无第三方服务;内网 http 环境直接可用;完全本地运行、零依赖。
按需选择入口:captureViewport 截取当前视口(推荐入口,支持完整参数);captureElement / captureElementSvg 截取任意元素(canvas / 矢量 SVG);canCapture 是可选的环境探测(供需要回退方案的调用方使用)。TypeScript 类型声明随包提供。
| API | 说明 | | --- | --- | | captureViewport | 截取当前视口(推荐入口,支持完整参数) | | captureElement | 截取任意 DOM 子树(元素本身) | | captureElementSvg | 截取任意 DOM 子树并输出 SVG dataURL(矢量,语法糖) | | canCapture | 能力探测:当前浏览器环境是否可用于截图 |
输出格式(format)统一为 canvas / svg / png / jpeg / webp / blob;返回类型随之不同,默认 canvas。
captureViewport
captureViewport(opts)截取当前视口(推荐入口,支持完整参数)。返回类型由 opts.format 决定,默认 Promise<HTMLCanvasElement>。当前版本聚焦视口截图(不做整页长图),列表滚动内容按当前显示状态截取。
| 参数 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | opts | object | — | 选项对象 | | opts.scale | number | 1 | 放大倍数(2 = 两倍清晰度) | | opts.hideSelectors | string | string[] | 无 | 需要从截图中剔除的元素选择器(如全屏遮罩) | | opts.mapCanvas | HTMLCanvasElement | object | null | null | 页面中的地图 canvas 元素(画面由 mapImageUrl 提供);地图位于同源 iframe 内时用分层写法(与 iframeImages 同构) | | opts.mapImageUrl | string | object | null | null | 地图当前帧 dataURL(不传则地图区域为空);地图位于同源 iframe 内时用分层写法 | | opts.iframeImages | Array | Map | object | null | 跨域 iframe 的画面(下标/键 = iframe 在页面中的序号;嵌套层用嵌套写法);仅在自动截取失败时启用 | | opts.format | string | canvas | 输出格式:canvas / svg / png / jpeg / webp / blob | | opts.quality | number | 浏览器默认 | 编码质量(0-1),仅对 jpeg / webp 生效 | | opts.resourceInterceptor | Function | null | 外部资源钩子:接管跨域图片 / 字体 / 样式表 | | opts.width | number | 视口宽 | 输出宽度 | | opts.height | number | 视口高 | 输出高度 |
captureElement
captureElement(el, opts)截取任意 DOM 子树(元素本身)。返回类型由 opts.format 决定,默认 Promise<HTMLCanvasElement>。输出尺寸自动跟随元素实测外框。元素是隔离渲染,因此依赖祖先的布局与选择器无法还原。
| 参数 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | el | Element | — | 目标元素(需已挂载在文档上) | | opts.scale | number | 1 | 放大倍数 | | opts.hideSelectors | string | string[] | 无 | 需要从截图中剔除的元素选择器 | | opts.background | string | transparent | 衬底背景色(元素自身透明时用) | | opts.mapCanvas | HTMLCanvasElement | object | null | null | 元素内的地图 canvas 元素(画面由 mapImageUrl 提供);地图位于同源 iframe 内时用分层写法(与 iframeImages 同构) | | opts.mapImageUrl | string | object | null | null | 地图当前帧 dataURL(不传则该区域可能为黑);地图位于同源 iframe 内时用分层写法 | | opts.iframeImages | Array | Map | object | null | 跨域 iframe 的画面(下标/键 = iframe 在元素内的序号;嵌套层用嵌套写法) | | opts.format | string | canvas | 输出格式:canvas / svg / png / jpeg / webp / blob | | opts.quality | number | 浏览器默认 | 编码质量(0-1),仅对 jpeg / webp 生效 | | opts.resourceInterceptor | Function | null | 外部资源钩子:接管跨域图片 / 字体 / 样式表 |
captureElementSvg
captureElementSvg(el, opts)截取任意 DOM 子树并输出 SVG dataURL(矢量),返回 Promise<string>——等价于 captureElement(el, { ...opts, format: 'svg' }) 的语法糖;参数与 captureElement 相同,但 format 固定为 svg,quality 不适用。相比 canvas:矢量可无损缩放,且不受画布尺寸上限限制,导出一定成功;代价是外链资源在通过 <img> 加载的 SVG 里不会加载(同源资源已随产物一并打包,取不到的仍按占位图处理)。
canCapture
canCapture(timeoutMs)能力探测:当前浏览器环境是否可用于截图。返回 Promise<boolean>——超时或失败返回 false,调用方据此回退到其它截图方案。
| 参数 | 类型 | 说明 | | --- | --- | --- | | timeoutMs | number | 探测超时(默认 45s) |
文档
- 离线文档包:文档站首页的「下载文档包」按钮可下载
dom-snap-x-apis.zip(两份 README 全文,含中英文完整 API 参考);npm 包内随附两份 README
许可
MIT
