【问题标题】:Integrating canvas into jsdom将画布集成到 jsdom 中
【发布时间】:2017-10-05 01:52:10
【问题描述】:

通过查看jsdom的文档,似乎支持canvas。然而,给出的唯一解释是:

jsdom 支持使用 canvas 或 canvas-prebuilt 包来使用 canvas API 扩展任何元素。为了使这项工作,您需要在项目中包含 canvas 作为依赖项,作为 jsdom 的对等点。如果 jsdom 可以找到 canvas 包,它会使用它,但如果它不存在,那么元素的行为就像 s。

这对我一点帮助都没有。我通过 npm 安装了 canvas-prebuilt 并在 jsdom 之前导入了 canvas-prebuilt

import canvas from 'canvas-prebuilt';
import jsdom from 'jsdom';

接下来我想创建一些 html sn-p 的 dom 对象,然后使用 html2canvas 将 html 插入到画布中:

const dom = new JSDOM(html);
let domcanvas = await html2canvas(dom, {
  dpi: dpi,
  useCORS: true,
  timeout: 20000
});

执行代码时会抛出错误:

No canvas support

我假设 jsdom 没有找到画布。

所以我的问题是如何将canvas集成到jsdom中?

编辑

所以在深入研究 JSDom 代码后,我发现 JSDom 实际上是在寻找画布。我通过修改 node_modules/jsdom/lib/jsdom/utils.js 中的代码,通过添加一些控制台日志来验证是否找到了画布,从而弄清楚了这一点:

exports.Canvas = null;
["canvas", "canvas-prebuilt"].some(moduleName => {
  try {
    exports.Canvas = require(moduleName);
    if (typeof exports.Canvas !== "function") {
      console.log(moduleName+' is not a function');
      // In browserify, the require will succeed but return an empty object
      exports.Canvas = null;
    }
    console.log('Successfully found ' + moduleName);
  } catch (e) {
    console.log('Cannot find ' + moduleName);
    exports.Canvas = null;
  }
  return exports.Canvas !== null;
});

在我的情况下,输出是:

找不到画布

成功找到canvas-prebuilt

因此,我最初的问题得到了回答。 抛出的错误来自 html2canvas,因为像 windowdocument 等对象不是全局的。一种解决方法是使它们全局化

global.window   = dom.window;
global.document = dom.window.document;
global.Image    = window.Image;
global.Node     = window.Node;

但是,@Niklas 已经提到了 html2canvas 和 jsdom 的更多问题,由于它们超出了本问题的范围,因此这里不再进一步讨论。

希望这个问题对某些人有所帮助。

【问题讨论】:

  • 可能“无画布支持”指的是import canvas from 'canvas-prebuilt';,而不是JSDOM。输入整个错误信息。
  • 即使你设法为 jsdom 添加了画布支持,jsdom 也缺乏 html2canvas 所需的许多其他功能,例如样式解析(即getComputedStyle)和布局计算(即getBoundingClientRect)跨度>
  • @GuilhermeNascimento 错误是由 html2canvas 引发的。引发错误的代码片段是var html2canvasExport = (typeof(document) === "undefined" || typeof(Object.create) !== "function" || typeof(document.createElement("canvas").getContext) !== "function") ? function() { return Promise.reject("No canvas support"); } : html2canvas;
  • @Niklas 好吧,这太糟糕了。我的主要问题是 IE11 污染了画布,因此当我尝试打印我的网站时,所有 svg 都是空白图像。我尝试了使用 canvg 的解决方法,但它似乎也不起作用。所以我看到的唯一选择是提供一个独立于客户端使用的网络浏览器的网络服务。
  • @KOsimo html2canvas 目前正在进行完全重写。如果您有一个问题的最小示例,您可以将它发布在 jsfiddle 上并在 github 上打开一个链接到它的问题吗?我会尽力修复 1.0.0 的发布

标签: express canvas html2canvas jsdom


【解决方案1】:

我复制了我的编辑以将其发布为我的问题的答案:

所以在深入研究 JSDom 代码后,我发现 JSDom 实际上是在寻找画布。我通过修改 node_modules/jsdom/lib/jsdom/utils.js 中的代码,通过添加一些控制台日志来验证是否找到了画布,从而弄清楚了这一点:

exports.Canvas = null;
["canvas", "canvas-prebuilt"].some(moduleName => {
  try {
    exports.Canvas = require(moduleName);
    if (typeof exports.Canvas !== "function") {
      console.log(moduleName+' is not a function');
      // In browserify, the require will succeed but return an empty object
      exports.Canvas = null;
    }
    console.log('Successfully found ' + moduleName);
  } catch (e) {
    console.log('Cannot find ' + moduleName);
    exports.Canvas = null;
  }
  return exports.Canvas !== null;
});

在我的例子中,输出是:

找不到画布

成功找到canvas-prebuilt

因此,我最初的问题得到了回答。 抛出的错误来自 html2canvas,因为像 windowdocument 等对象不是全局的。一种解决方法是使它们全局化

global.window   = dom.window;
global.document = dom.window.document;
global.Image    = window.Image;
global.Node     = window.Node;

但是,@Niklas 已经提到了 html2canvas 和 jsdom 的更多问题,由于它们超出了本问题的范围,因此这里不再进一步讨论。

希望这个问题对某些人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 2017-11-23
    • 2018-10-06
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    相关资源
    最近更新 更多