【问题标题】:How can I run a javascript as a node.js script without the DOM?如何在没有 DOM 的情况下将 javascript 作为 node.js 脚本运行?
【发布时间】:2014-03-14 05:59:21
【问题描述】:

https://github.com/jasondavies/d3-cloud 是使用 D3 库的 javascript 中的词云。 This is an interactive demo。该演示使用 d3-cloud 脚本在 HTML 中生成 SVG。

我想在服务器端使用它并让 node.js 为我生成一个 SVG 文件,并在我更新数据时将其保存到磁盘,而不是将 D3 库加载到浏览器并在那里渲染。有没有办法做到这一点?我可以使用看似依赖 HTML DOM 而没有 DOM 的库吗?

我是 node.js 的新手

【问题讨论】:

  • “我可以使用似乎依赖于没有 DOM 的 HTML DOM 的库吗”:不,这就像开车没有汽车一样。
  • 您可以查看Phantom.js,这可能更适合此类任务。
  • 既然 svg 是 xml,你可以通过添加 xml2js 模块来使用 xml 吗?只是一个想法..我也不熟悉node.js
  • @TheHippo - phantomJS 对我很有帮助。谢谢你。我本可以选择这个作为答案:-)

标签: javascript node.js svg d3.js


【解决方案1】:

我接受了TheHippo's的建议并使用了PhantomJS,我创建了一个JS-

svggen.js:

var page = require('webpage').create(),
    url = 'http://www.example.com/wordcloud.html';

page.open(url, function (status) {
    if (status !== 'success') {
        console.log('Unable to access network');
    } else {
        var svgData = page.evaluate(function(s){
                var serializer = new XMLSerializer();
                var element = document.getElementById("svg1");
                return serializer.serializeToString(element);
        });
        console.log("<?xml version=\"1.0\"?>"+svgData);
    }
    phantom.exit();
});

wordcloud.html:

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="d3.min.js"></script>
<script src="d3.layout.cloud.js"></script>
<script>
  var fill = d3.scale.category20();

  d3.layout.cloud().size([500, 800])
      .words([
        "Hello", "world", "normally", "you", "want", "more", "words",
        "than", "this"].map(function(d) {
        return {text: d, size: 10 + Math.random() * 90};
      }))
      .padding(5)
      .rotate(function() { return ~~(Math.random() * 2) * 90; })
      .font("Impact")
      .fontSize(function(d) { return d.size; })
      .on("end", draw)
      .start();

  function draw(words) {
    d3.select("body").append("svg")
        .attr("width", 500)
        .attr("height", 800)
        .attr("id","svg1")
        .attr("xmlns","http://www.w3.org/2000/svg")
        .attr("xmlns:xlink","http://www.w3.org/1999/xlink")
      .append("g")
        .attr("transform", "translate(150,150)")
      .selectAll("text")
        .data(words)
      .enter().append("text")
        .style("font-size", function(d) { return d.size + "px"; })
        .style("font-family", "Impact")
        .style("fill", function(d, i) { return fill(i); })
        .attr("text-anchor", "middle")
        .attr("transform", function(d) {
          return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
        })
        .text(function(d) { return d.text; });
  }
</script>
</body></html>

然后我运行

phantomjs svggen.js > svgFile.svg

生成的 svgFile.svg 是一个独立的 SVG 文件。对于 d3cloud,请查看 this

【讨论】:

  • 我得去看看 PhantomJS。看起来它完成了我认为可以用 node.js 完成的所有事情!
  • 没有。 PhantomJS 是一个无头浏览器和一个 JS 测试器。在我使用它的时候,我认为它的域与 node.js 没有太多重叠。而且我不是 node.js 专家。
  • 我明白了。因此,您需要同时运行一个服务器,该服务器还可以使用 Javascript 动态构建网站。
【解决方案2】:

查看jsdom。您可以访问窗口上下文,然后您可以执行 d3 操作。然后使用node file 将其保存到文件系统

// Count all of the links from the Node.js build page
var jsdom = require("jsdom");

jsdom.env(
  "http://nodejs.org/dist/",
  ["http://code.jquery.com/jquery.js"],
  function (errors, window) {
    console.log("there have been", window.$("a").length, "nodejs releases!");
  }
);

【讨论】:

  • 别忘了jsdom需要canvas包才能使用链接脚本中提到的canvas方法...
  • 我在 EC2 上运行并且在获取 canvas 包时遇到了严重问题。所以我接受了@TheHippo 的建议并使用了 phantomJS。如果我可以安装软件包,我相信这会奏效:-(
【解决方案3】:

您可以通过创建document fragment 来创建没有文档的 DOM。一旦你有了它,你可以将一个根&lt;svg&gt; 元素附加到它,然后将该节点传递给d3.select(node)。从那里开始,其余的 d3 方法应该正常工作。

【讨论】:

  • 如何在 node.js 中制作文档片段?
  • 这是一个很好的问题...我找不到关于 node.js 是否支持独立的 new DocumentFragment() 构造函数的任何参考。 (在浏览器中创建文档片段最受支持的方法是在主文档上使用方法调用,这对您没有好处。)这个module in npm 似乎可以完成这项工作,但我看不到完整的代码不运行 npm。
【解决方案4】:

如果你只是用 d3.js 渲染一个 svg,你就不需要 phantomjs

你可以直接在 node.js 中运行 d3

global.d3 = d3 = require "d3"
cloud     = require 'd3.layout.cloud'
fs = require 'fs'

draw = (words) ->
  d3.select("body").append("svg").attr("width", 500).attr("height", 800).attr("id", "svg1").attr("xmlns", "http://www.w3.org/2000/svg").attr("xmlns:xlink", "http://www.w3.org/1999/xlink").append("g").attr("transform", "translate(150,150)").selectAll("text").data(words).enter().append("text").style("font-size", (d) ->
    d.size + "px"
  ).style("font-family", "Impact").style("fill", (d, i) ->
    fill i
  ).attr("text-anchor", "middle").attr("transform", (d) ->
    "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"
  ).text (d) ->
    d.text

fill = d3.scale.category20()
cloud().size([500, 800]).words(["Hello", "world", "normally", "you", "want", "more", "words", "than", "this"].map((d) ->
  text: d
  size: 10 + Math.random() * 90
)).padding(5).rotate(->
  ~~(Math.random() * 2) * 90
).font("Impact").fontSize((d) ->
  d.size
).on("end", draw).start()

svg = d3.select('body').node().innerHTML

console.log svg
fs.writeFile 'svgFile.svg', svg

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-19
    • 2016-04-17
    • 2018-12-10
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    • 2017-12-15
    • 1970-01-01
    相关资源
    最近更新 更多