dom-to-image 解决 html2canvas 图片不支持css filter属性

github:https://github.com/tsayen/dom-to-image

这是什么

dom-映像是一个库,可以将任意 DOM 节点转换为以 JavaScript 编写的矢量 (SVG) 或栅格 (PNG 或 JPEG) 图像。它基于保罗·巴考斯的domvas,已经完全重写,一些错误固定和一些新功能(如网络字体和图像支持)添加。

安装

Npm

npm install dom-to-image

然后加载

/* in ES 6 */
import domtoimage from 'dom-to-image';
/* in ES 5 */
var domtoimage = require('dom-to-image');

鲍尔

bower install dom-to-image

在页面中包括 或 ,它将使变量在全局范围内可用。src/dom-to-image.jsdist/dom-to-image.min.jsdomtoimage

<script src="path/to/dom-to-image.min.js" />
<script>
  domtoimage.toPng(node)
  //...
</script>

使用

所有顶级函数都接受 DOM 节点和呈现选项,并返回承诺,这些承诺通过相应的数据 URL 实现。
获取 PNG 映像基础 64 编码的数据 URL 并马上显示:

var node = document.getElementById('my-node');

domtoimage.toPng(node)
    .then(function (dataUrl) {
        var img = new Image();
        img.src = dataUrl;
        document.body.appendChild(img);
    })
    .catch(function (error) {
        console.error('oops, something went wrong!', error);
    });

获取 PNG 图像 Blob 并下载它(例如,使用 FileSaver):

domtoimage.toBlob(document.getElementById('my-node'))
    .then(function (blob) {
        window.saveAs(blob, 'my-node.png');
    });

保存并下载压缩的 JPEG 映像:

domtoimage.toJpeg(document.getElementById('my-node'), { quality: 0.95 })
    .then(function (dataUrl) {
        var link = document.createElement('a');
        link.download = 'my-image-name.jpeg';
        link.href = dataUrl;
        link.click();
    });

获取 SVG 数据 URL,但筛选出所有元素:<i>

function filter (node) {
    return (node.tagName !== 'i');
}

domtoimage.toSvg(document.getElementById('my-node'), {filter: filter})
    .then(function (dataUrl) {
        /* do something */
    });

使用每 4 个数组元素表示像素的RGBA 数据,将原始像素数据作为 Uint8Array 获取:

var node = document.getElementById('my-node');

domtoimage.toPixelData(node)
    .then(function (pixels) {
        for (var y = 0; y < node.scrollHeight; ++y) {
          for (var x = 0; x < node.scrollWidth; ++x) {
            pixelAtXYOffset = (4 * y * node.scrollHeight) + (4 * x);
            /* pixelAtXY is a Uint8Array[4] containing RGBA values of the pixel at (x, y) in the range 0..255 */
            pixelAtXY = pixels.slice(pixelAtXYOffset, pixelAtXYOffset + 4);
          }
        }
    });

impl 下的所有函数不是公共 API,并且仅公开用于单元测试。


渲染选项

滤波器

以 DOM 节点作为参数的函数。如果传递的节点应包含在输出中(不包括节点意味着也不包括其子节点),应返回 true。未在根节点上调用。

bgcolor

背景颜色的字符串值,任何有效的 CSS 颜色值。

高度、宽度

渲染前要应用于节点的高度和宽度(以像素为单位)。

风格

在渲染之前要将其属性复制到节点样式的对象。您可能需要检查此引用的CSS 属性的 JavaScript 名称。

质量

表示图像质量的介于 0 和 1 之间的数字(例如 0.92 ±> 92%)JPEG 图像。默认值为 1.0 (100%)

缓存布斯特

设置为 true 以将当前时间作为查询字符串追加到 URL 请求,以启用缓存破坏。默认值为 false

图像位置持有人

获取图像时将使用的占位符图像的数据 URL 失败。默认值为未定义,并将对失败的图像引发错误

浏览器

它测试了最新的Chrome和Firefox(在编写时分别是49和45),Chrome在大DOM树上的表现明显更好,可能是因为它更具有性能的SVG支持,而且它支持属性。CSSStyleDeclaration.cssText

Internet 资源管理器不受(并且不会)支持,因为它不支持 SVG <外国对象>标记

Safari不受支持,因为它在 < 外国对象> 标记上使用更严格的安全模型。建议的解决方法是使用toSvg 并在服务器上呈现。`

依赖

当前仅使用标准 lib,但请确保您的浏览器支持:

  • 承诺
  • SVG 标签<foreignObject>

测试

最重要的是,测试取决于:

  • js-imagediff,比较渲染和控制图像

  • ocrad .js,对于无法比较图像(由于浏览器呈现差异)时的部分,只需测试文本是否呈现

工作原理

也许有一天存在(或者可能已经存在?)一种将 HTML 的某些部分导出到图像的简单而标准的方法(然后这个脚本只能作为所有为了完成如此明显的事情而必须跳过的所有圈套的证据),但到目前为止我还没有找到一个。

此库使用 SVG 的功能,允许在标记内具有任意 HTML 内容。因此,为了呈现该 DOM 节点,请执行以下步骤:<foreignObject>

  1. 递归克隆原始 DOM 节点

  2. 计算节点和每个子节点的样式,并将其复制到相应的克隆

    • 不要忘记重新创建伪元素,因为它们不是任何形式的克隆,当然
  3. 嵌入 Web 字体

    • 查找可能表示 Web 字体的所有声明@font-face

    • 解析文件 URL,下载相应的文件

    • 基64编码和内联内容作为 URLdata:

    • 连接所有处理的 CSS 规则,并将其放入一个元素中,然后将其附加到克隆<style>

  4. 嵌入图像

    • 在元素中嵌入图像 URL<img>

    • CSS 属性中使用的内联图像,其方式类似于字体background

  5. 将克隆的节点序列化为 XML

  6. 将 XML 包装到标记中,然后包装到 SVG 中,然后将其作为数据 URL<foreignObject>

  7. 此外,若要将 PNG 内容或原始像素数据作为 Uint8Array 获取,请创建一个图像元素,将 SVG 作为源,并在屏幕外画布上呈现它,您也创建了该画布,然后从画布上读取内容

  8. 做!

需要注意的事情

  • 如果要渲染的 DOM 节点包含一个元素,该元素上绘制了一些内容,则应该处理得很好,除非画布污染 - 在这种情况下,渲染将不成功。<canvas>

  • 在编写本文时,Firefox 对一些外部样式表有问题(请参阅问题#13)。在这种情况下,将捕获并记录错误。

作者

阿纳托利·赛延科,保罗·巴考斯(原创想法)

许可证

麻省理工学院

posted @   夏秋初  阅读(2797)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示