【问题标题】:How to use D3 in Node.js properly?如何在 Node.js 中正确使用 D3?
【发布时间】:2012-03-30 18:14:29
【问题描述】:

我一直在尝试在 Node.js 中调用 D3。我首先尝试使用脚本标签从 D3 的网站导入 d3.v2.js,但随后阅读了此线程:

I want to run d3 from a Cakefile

D3 的作者建议应该'npm install d3'...我这样做了,我可以在节点控制台中成功调用它:

dpc@ananda:$ node
> var d3 = require("d3");
undefined
> d3.version;
'2.8.1' 

但是,当尝试使用“node app.js”从 app.js 调用它时,我得到:

node.js:201
    throw e; // process.nextTick error, or 'error' event on first tick
          ^
TypeError: Cannot read property 'BSON' of undefined
at     /Users/dpc/Dropbox/sync/Business/MindfulSound/Development/nad.am/nadam/node_modules/mongoose/node_modules/mongodb/lib/mongodb/index.js:45:44

我意识到在其他地方,D3 的作者已经明确指出应该需要画布:

https://github.com/mbostock/d3/blob/master/examples/node-canvas/us-counties.js

作为:

var Canvas = require("canvas");

但即便如此,(即使在 app.js 的 require 语句中特别需要 index.js 而不是 d3.v2.js),我也无法在 Jade 模板中使用以下内容:

- script('/javascripts/d3.v2.js')
h1 Dashboard
  section.css-table
    section.two-column
      section.cell
        hr.grey
        h2 Statistics
        #mainGraph
            script(type="text/javascript") 
              var Canvas = require("canvas");
              var w = 400,
                  h = 400,
                  r = Math.min(w, h) / 2,
                  data = d3.range(10).map(Math.random).sort(d3.descending),
                  color = d3.scale.category20(),
                  arc = d3.svg.arc().outerRadius(r),
                  donut = d3.layout.pie();
              var vis = d3.select("body").append("svg")
                  .data([data])
                  .attr("width", w)
                  .attr("height", h);
              var arcs = vis.selectAll("g.arc")
                  .data(donut)
                  .enter().append("g")
                  .attr("class", "arc")
                  .attr("transform", "translate(" + r + "," + r + ")");
              var paths = arcs.append("path")
                  .attr("fill", function(d, i) { return color(i); });
              paths.transition()
                  .ease("bounce")
                  .duration(2000)
                  .attrTween("d", tweenPie);
              paths.transition()
                  .ease("elastic")
                  .delay(function(d, i) { return 2000 + i * 50; })
                  .duration(750)
                  .attrTween("d", tweenDonut);

              function tweenPie(b) {
                b.innerRadius = 0;
                var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
                return function(t) {
                  return arc(i(t));
                };
              }

              function tweenDonut(b) {
                b.innerRadius = r * .6;
                var i = d3.interpolate({innerRadius: 0}, b);
                return function(t) {
                  return arc(i(t));
                };

      section.cell
        hr.grey
        h2 Achievements

【问题讨论】:

    标签: node.js d3.js


    【解决方案1】:

    在Node中使用D3的正确方法是使用NPM安装d3然后require它。您可以 npm install d3 或使用 package.json 文件,然后是 npm install:

    {
      "name": "my-awesome-package",
      "version": "0.0.1",
      "dependencies": {
        "d3": "3"
      }
    }
    

    在 node_modules 目录中有 d3 后,通过 require 加载它:

    var d3 = require("d3");
    

    就是这样。

    关于您的其他问题:使用 D3 不需要画布。您链接的节点画布示例需要画布,因为它呈现到画布。 TypeError (Cannot read property 'BSON' of undefined) 似乎与您使用 mongoose / monogdb 相关,而不是 D3。

    【讨论】:

    • 感谢您的回复!这很奇怪:d3 确实在 node_modules 中,因为我使用 'npm install d3' 安装它......但是 'var d3 = require("d3");'在 app.js 中给了我 BSON 错误...删除该行,BSON 错误消失了。这是一个更简单的 d3 使用示例,来自此处的 SVG 圆图:christopheviau.com/d3_tutorial
    • 记录在案,发现mongoose和d3之间使用全局变量存在问题,因此首先调用d3 var d3 = require("d3");在要求 mongoose 解决 BSON 错误问题之前。
    • 现在我在 node.js 中有 d3 作为一个模块,如何使用它选择元素?我想在服务器上创建一个 svg 并将其返回给客户端。 d3.select() 可以像 '
      ' 那样采用 html sn-p 吗?
    • 这是一个容易混淆的话题,所以让我试着帮助澄清一下 - npm install d3 加载 d3 节点模块,它允许您在服务器上的内存中构建数据驱动的文档,以便将它们传递给浏览器预构建(渲染)html/svg/等。将此与传统的 d3 用法进行比较,后者是将库包含在 html 中,并在浏览器中渲染 dom 中的元素。客户端与服务器端的渲染存在细微但显着的差异。另请参阅:mango-is.com/blog/engineering/…
    • 我的理解是服务端d3需要一个伪dom来select()。看看 JSDOM。我发现这篇文章很有启发性mango-is.com/blog/engineering/…
    【解决方案2】:

    使用 ES6 的 import 而不是 require

    import * as d3 from 'd3';
    

    这对于任何有经验的 babel/ES6 用户来说可能是显而易见的,我知道这是一个老问题,但我来到这里是为了解决这个问题。希望这对某人有帮助。

    更多关于importrequire 的信息见here.

    【讨论】:

      【解决方案3】:

      您需要使用 yarn 或 npm 安装 jsdom。 Node.js 默认不支持 dom,因此需要使用 jsdom 来创建 dom 元素。将 d3 用于除 fetch 操作之外的所有其他操作。即 d3.xml,d3.tsv

      import jsdom from 'jsdom';
      import * as d3 from 'd3';
      const { JSDOM } = jsdom;
      JSDOM.fromURL(
          'your resource url',
        ).then((dom) => {
          const doc = dom.window.document;
          const states = d3
            .select(doc)
            .select('path')
            .attr(':fme:ID');
          console.log(states);
        });
      

      从文件创建 dom

      JSDOM.fromURL(
          'your resource url',
        ).then((dom) => {
          const doc = dom.window.document;
      }
      

      来自html字符串的dom

      const dom = new JSDOM(
        `<p>Hello
          <img src="foo.jpg">
        </p>`,
        { includeNodeLocations: true }
      );
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-25
        • 2017-05-11
        • 2012-06-16
        • 1970-01-01
        相关资源
        最近更新 更多