别再用 html2canvas 了!Snapdom 才是网页截图与海报生成的王者
SnapDOM 与 html2canvas 选型两者都是纯前端、将 DOM 元素导出为图片的库适用于分享卡片、海报生成、工单截图、导出报告等场景。说明SnapDOM它通过克隆 DOM SVGforeignObject借助浏览器原生渲染引擎完成截图是 html2canvas 的现代替代方案。SnapDOM GitHub 仓库github.com/zumerlab/snapdomhtml2canvas 同样是一个开源项目GitHub 仓库github.com/niklasvh/html2canvas目录SnapDOM 与 html2canvas 选型一、能实现什么SnapDOM[zumer/snapdom](https://github.com/zumerlab/snapdom)html2canvas[html2canvas](https://html2canvas.hertzen.com/)共同局限二、实现原理SnapDOM克隆 DOM 浏览器渲染html2canvas遍历 DOM JS 重绘 Canvas三、差异对比SnapDOM 浏览器支持html2canvas 浏览器支持四、哪种更好五、其他类似库六、快速用法SnapDOMhtml2canvas七、总结一、能实现什么SnapDOMzumer/snapdom将任意 DOM 子树导出为PNG、JPG、WebP、SVG、Canvas、Blob支持Shadow DOM、伪元素::before/::after、CSS 变量、counter()/counters()、line-clamp支持同源iframe截图可嵌入 Web 字体、背景图、外链图片跨域需代理插件体系PDF 导出、水印、自定义后处理等一次克隆、多次导出const result await snapdom(el)html2canvashtml2canvas将 DOM 绘制到Canvas再通过toDataURL/toBlob得到 PNG/JPG支持常见 2D 样式背景色、边框、文字、部分渐变与阴影配置项丰富scale、useCORS、backgroundColor、ignoreElements等生态成熟、示例多但官方自 2022 年后无稳定版发布README 仍标注实验性质共同局限无法截取跨域且未开启 CORS 的图片/字体会空白或污染 Canvas无法截取video当前帧、WebGL 画布、部分原生控件不是「整页滚动长截图」专用方案需自行拼接或换方案浏览器安全策略限制下无法截取用户未授权的页面内容二、实现原理SnapDOM克隆 DOM 浏览器渲染DOM 元素 → 深克隆含 Shadow DOM → 内联计算样式、伪元素、字体、图片 → 包裹进 SVG foreignObject → 序列化为 data:image/svgxml → 转为 PNG / JPG / WebP / Blob核心思路不自己画像素而是把「浏览器已经会画的东西」交给浏览器画。简化原理代码// 1. 克隆节点并内联样式constcloneelement.cloneNode(true);inlineComputedStyles(clone);inlinePseudoElements(clone);// ::before / ::after → 真实 DOM 节点awaitinlineImagesAndFonts(clone);// 2. 包进 SVG foreignObjectconstsvgsvg xmlnshttp://www.w3.org/2000/svg width${w} height${h} foreignObject width100% height100% div xmlnshttp://www.w3.org/1999/xhtml${clone.outerHTML}/div /foreignObject /svg;constsvgUrldata:image/svgxml;charsetutf-8,encodeURIComponent(svg);// 3. 栅格化为位图constimgnewImage();img.srcsvgUrl;awaitimg.decode();constcanvasdocument.createElement(canvas);canvas.getContext(2d).drawImage(img,0,0);html2canvas遍历 DOM JS 重绘 CanvasDOM 元素 → 递归遍历每个节点 → 读取 getComputedStyle → 用 Canvas 2D API 模拟 CSS 绘制 → 输出 Canvas核心思路在 JavaScript 里重新实现一套 CSS 绘制器不依赖 SVG foreignObject。简化原理代码asyncfunctionhtml2canvas(element,options){constcanvasdocument.createElement(canvas);constctxcanvas.getContext(2d);constboundselement.getBoundingClientRect();canvas.widthbounds.width*options.scale;canvas.heightbounds.height*options.scale;asyncfunctionrenderNode(node){if(node.nodeTypeNode.TEXT_NODE){drawText(ctx,node,getComputedStyle(node.parentElement));return;}conststylegetComputedStyle(node);drawBackground(ctx,node,style);// 颜色、渐变部分支持drawBorder(ctx,node,style);drawBoxShadow(ctx,node,style);// 有限支持for(constchildofnode.childNodes){awaitrenderNode(child);}// 伪元素需额外处理且支持不完整}awaitrenderNode(element);returncanvas;}三、差异对比维度SnapDOMhtml2canvas渲染方式克隆 SVG foreignObject浏览器原生绘制JS 遍历 DOMCanvas 2D 模拟 CSS性能通常快一个数量级以上官方基准简单元素约 30–100×复杂 DOM 明显变慢伪元素较完整内联为真实节点部分支持易丢失Shadow DOM支持不支持CSS 变量完整部分counter()支持不支持输出格式SVG、PNG、JPG、WebP、Canvas、Blob主要 PNG/JPG经 Canvas插件扩展有无维护状态活跃更新2025–20262019–2022 后几乎停更依赖0少量css-line-break 等上手难度简单API 更现代简单文档与案例多兼容性现代浏览器更广的老浏览器覆盖SnapDOM 浏览器支持浏览器支持版本说明Chrome / Edge90完全支持原生性能Firefox88完全支持原生性能Safari / WebKit14完全支持但需特殊处理如预热机制Mobile Safari (iOS)iOS 14完全支持同样需要预热Chrome Android90完全支持特别说明SnapDOM 在 Safari 上需要额外的“预热”流程来确保字体和图片加载完成并会自动将 box-shadow 转换为 filter: drop-shadow 以保证渲染效果。html2canvas 浏览器支持现代版本如 c2stack/html2canvas 1.4.1要求浏览器原生支持 ES2020。浏览器支持版本Chrome80Firefox75Safari13.1Edge80传统版本含 Polyfill通过引入 es6-promise 等 Polyfill可以支持更古老的浏览器Firefox 3.5Google ChromeOpera 12IE9Safari 6四、哪种更好新项目优先选 SnapDOM理由性能更好大节点、复杂样式下差距明显还原度更高伪元素、Shadow DOM、CSS 变量等更接近真实页面持续维护bug 修复与新特性在跟进API 更顺手toPng/toSvg/download一步到位仍可考虑 html2canvas 的情况维护老项目已有大量 html2canvas 集成代码需要兼容非常老的浏览器环境只需极简 DOM、样式简单、性能要求不高需要服务端高质量整页截图时两者都不是最优解应改用Puppeteer / Playwright等无头浏览器方案。五、其他类似库库特点备注html-to-image基于 dom-to-image 改进SVG foreignObject 思路轻量维护中等dom-to-image早期 foreignObject 方案已较少维护dom-to-image-moredom-to-image 分支修复部分 bug社区 forkmodern-screenshot现代 API性能较好SnapDOM 竞品之一rasterizeHTML.jsHTML/SVG 转 Canvas偏底层html-to-image-pro商业增强版付费能力Puppeteer / Playwright服务端真实浏览器截图还原度最高需后端浏览器原生drawElementImage实验性 WICG API未来可能替代前端库六、快速用法SnapDOMimport{snapdom}fromzumer/snapdom;consteldocument.querySelector(#card);constimgawaitsnapdom.toPng(el);document.body.appendChild(img);CDNESMscripttypemoduleimport{snapdom}fromhttps://cdn.jsdelivr.net/npm/zumer/snapdom2/dist/snapdom.mjs;constimgawaitsnapdom.toPng(document.querySelector(#card));/scripthtml2canvasconstcanvasawaithtml2canvas(document.querySelector(#card),{scale:window.devicePixelRatio,useCORS:true,});document.body.appendChild(canvas);CDNscriptsrchttps://cdn.jsdelivr.net/npm/html2canvas1.4.1/dist/html2canvas.min.js/script七、总结场景推荐新项目、复杂样式、追求性能与还原度SnapDOM老项目迁移成本高、样式极简html2canvas 可继续用服务端 PDF/整页/像素级一致Puppeteer / Playwright轻量 foreignObject 方案html-to-image / modern-screenshot本地可直接打开snapdom-demo.html与html2canvas-demo.html对比效果若 CDN 加载失败请检查网络或使用本地 HTTP 服务访问。