【问题标题】:How to use D3 force layout with existing SVG elements as nodes如何将现有 SVG 元素作为节点使用 D3 强制布局
【发布时间】:2013-04-19 02:19:00
【问题描述】:

我有一个 javascript 对象数组,其中每个对象都有 .ui 属性,该属性包含 现有 各种类型的 SVG 形状/元素(内部包含其他元素的自包含“g”元素)。

我想将这些对象排列为 D3 中的力图布局。因此,我不想让 d3 创建圆圈(或其他任何东西),而是将我的 ui 对象之一分配给图形。

我为此创建了一个simplified fiddle << HERE >>。预先存在且应成为图表一部分的对象是 3 个彩色矩形。在这个例子中,我没有做到这一点。 d3 append 命令只能用于构造形状/元素,但不能附加已构造的形状/元素。我试图这样做,但它无法在 D3 中工作:

node.append( function(d) { d.ui.node(); }) ...

... 如前所述,这不起作用,因为 d3 不附加元素。

 var svgContainer = d3.select("#svgContainer");

// =============================================================    
// creates the SVG elements to be used ( 3 colored rectangles )
// =============================================================

var element0a = svgContainer.append("g").attr("transform","translate(100,100)");
var element0b = element0a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","red");

var element1a = svgContainer.append("g").attr("transform","translate(100,200)");
var element1b = element1a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","green");

var element2a = svgContainer.append("g").attr("transform","translate(100,300)");
var element2b = element2a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","blue");

// =============================================================
// fills up an object array that contains details plus the UI attribute
// =============================================================

var nodeArray = new Array();
nodeArray[0] = { id : "000", label : "label 000", ui : element0a };
nodeArray[1] = { id : "001", label : "label 001", ui : element1a };
nodeArray[2] = { id : "002", label : "label 002", ui : element2a };

// not interested in dealing with the edge/link right now, just empty
var linkArray = new Array();


// =============================================================
// D3 force layout stuff
// =============================================================

var force = self.force = d3.layout.force()
    .nodes(nodeArray)
    .links(linkArray)
    .gravity(.05)
    .distance(80)
    .charge(-100)
    .size([600, 600])
    .start();

var node = svgContainer.selectAll("g.node")
    .data(nodeArray)
    .enter().append("svg:g")
    .attr("class", "node")
    .call(force.drag);

// HERE (below) COMES THE ISSUE, where you see append("cicle") I want to append the nodeArray's ".ui" element. 

node.append("circle")          // <--- 
    .attr("class", "node")
    .attr("r",10)
    .attr("fill","orange")
    .call(force.drag);

force.on("tick", function() {
      node.attr("transform", function(d) {return "translate(" + d.x + "," + d.y + ")";});
    });

【问题讨论】:

  • 您应该可以使用.select() 选择已经存在的元素。您可能想为他们提供单独的 ID,这样可以更轻松地选择它们。
  • 好建议。实际上,我应该简单地选择现有元素,而不是使用 enter() 阶段。总体而言,如果您不需要创建,则无需 enter()。

标签: svg d3.js force-layout


【解决方案1】:

基于Lars Kotfoff 的建议:

工作小提琴here

如果要绘制的元素已经存在,只需跳过 enter() D3 阶段并根据元素的共同特征(类名)使用 select() 或 selectAll()例如 )。

这就是元素的创建方式(添加了一个特定的类以允许隔离选择):

var element0a = svgContainer.append("g").attr("class","node").attr("transform","translate(100,100)");
var element0b = element0a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","red");

这是替换 enter() 阶段的代码的一部分

var node = svgContainer.selectAll("g.node")
    .data(nodeArray)
    .call(force.drag);

这是被删除的内容

var node = svgContainer.selectAll("g.node")
    .data(nodeArray)
    .enter().append("svg:g")
    .attr("class", "node")
    .call(force.drag);

// HERE (below) COMES THE ISSUE, where you see append("cicle") I want to append the nodeArray's ".ui" element. 

node.append("circle")          // <--- 
    .attr("class", "node")
    .attr("r",10)
    .attr("fill","orange")
    .call(force.drag);

【讨论】:

    【解决方案2】:

    问题是您将元素附加到svgContainer 以创建它们,因此它们已经附加到某些东西上。

    我建议的解决方法是将元素属性存储在 json 文件中,然后从 json 中读取配置。

    可能会有更优雅的东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-18
      • 1970-01-01
      • 2012-09-10
      • 2014-06-30
      • 1970-01-01
      • 2014-10-24
      • 2017-12-07
      • 2012-07-13
      相关资源
      最近更新 更多