【问题标题】:d3: Optionally add child elements based on node content in force layout - when filter is not the solutiond3:在强制布局中根据节点内容可选地添加子元素 - 当过滤器不是解决方案时
【发布时间】:2014-08-27 18:04:40
【问题描述】:

我正在尝试为这个问题提供一个可能的解决方案:d3 force layout with node groups

我有一个类似这样的 JSON:

{
    nodes: [
        {
            label: "x"
            inputs: [],
            outputs: ["a"]
        },
        {
            label: "y"
            inputs: ["b"],
            outputs: []
        },
        ...
    ],
    links: [
        {
            source: 0, //x
            sourceIndex: 0, //x.outputs.a
            target: 1, //y
            targetIndex: 0 //y.inputs.b
        },
        ...
    ]
}

我想为每个节点构建一个 SVG,如下所示:

    <g class="component worker" transform="translate(0,0)">
        <use class="container" xlink:href="#container"/>
        <use class="icon" xlink:href="#worker"/>
        <text class="label" text-anchor="middle" alignment-baseline="middle" dy="40">Worker</text>
        <g class="input" transform="translate(-31,-16)">
            <use class="port" xlink:href="#port">
                <title>stdin</title>
            </use>
            <use y="8" class="port" xlink:href="#port"/>
            <use y="16" class="port" xlink:href="#port"/>
            <use y="24" class="port" xlink:href="#port"/>
            <use y="32" class="port" xlink:href="#port"/>
        </g>
        <g class="output" transform="translate(31,16)">
            <use class="port" xlink:href="#port">
                <title>stdout</title>
            </use>
            <use y="-8" class="port" xlink:href="#port"/>
            <use y="-16" class="port" xlink:href="#port"/>
            <use y="-24" class="port" xlink:href="#port"/>
            <use y="-32" class="port" xlink:href="#port"/>
        </g>
    </g>

我有以下 js 代码来构建 SVG:

    var node = svg.selectAll(".node").data(this.data.nodes).enter().append("g").attr({
        "class": function (d) {
            return d.groups.join(" ");
        }
    }).call(force.drag);
    node.append("use").attr({
        "class": "container",
        "xlink:href": "#container"
    });
    node.append("use").attr({
        "class": "icon",
        "xlink:href": function (d) {
            return d.icon;
        }
    });
    node.append("text").attr({
        "class": "label",
        "text-anchor": "middle",
        "alignment-baseline": "middle",
        dy: 40
    }).text(function (d) {
        return d.label
    });

    node.append("g").attr({
        "class": "input",
        transform: "translate(-31,-16)"
    });

    node.append("g").attr({
        "class": "output",
        transform: "translate(31,16)"
    });

现在我缺少的是输入和输出。我不知道如何迭代节点的那些属性,以及如何使用 d3.js 的流畅接口将它们一一追加。我检查了d3: Optionally add child elements based on node content in force layout,但过滤在这里不起作用,因为我们讨论的是迭代集合,而不是检查属性的存在。有什么建议吗?

【问题讨论】:

    标签: javascript svg d3.js force-layout


    【解决方案1】:

    您可以为此使用嵌套选择。

    我假设您希望在节点数据中为 inputs 数组的每个成员附加一个项目的输入,对于输出也是如此。

    例如,输入:

    node.append("g").attr({
        "class": "input",
        transform: "translate(-31,-16)"
    })
    .selectAll('SOME_THING')
      .data(function(d) { return d.inputs; })
      .enter().append('SOME_THING')
    

    'SOME_THING' 是您要附加的元素(可能是 &lt;use&gt;,尽管从您的示例输出中不清楚这些元素映射到的位置)。

    【讨论】:

      【解决方案2】:

      我用each()解决了这个问题:

          node.each(function (d) {
              var node = d3.select(this);
              var inputs = node.append("g").attr({
                  "class": "input",
                  transform: "translate(-31,-16)"
              });
              d.inputs.forEach(function (name, index) {
                  inputs.append("use").attr({
                      y: -8 * index,
                      "xlink:href": "#port"}).append("title").text(name);
              });
          });
      

      但我会使用 jshanley 的解决方案,我猜这是 d3 方式... :-)

          var inputs = node.append("g").attr({
              "class": "input",
              transform: "translate(-31,-16)"
          });
          inputs.selectAll("use").data(function (d) {
              return d.inputs;
          }).enter().append("use").attr({
              y: function (d, index) {
                  return -8 * index;
              },
              "xlink:href": "#port"
          }).append("title").text(String);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-24
        • 2014-11-20
        • 2012-03-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多