【问题标题】:arrays and nodes mapping in d3 forced3 force 中的数组和节点映射
【发布时间】:2023-03-29 13:50:01
【问题描述】:

假设在 d3 中我有几个这样的数据数组:

节点:

var nodes = [
{"name": "abc", "type": "Db"},
{"name": "def", "type": "Db"},
{"name": "ghi", "type": "Db"},
{"name": "jkl", "type": "Db"}
]

链接:

var links = [
{source: nodes[0], target: nodes[1]},
{source: nodes[0], target: nodes[2]},
{source: nodes[1], target: nodes[3]}
]

有没有一种方法可以使用名称而不是数字?像这样:

var links = [
{source: nodes["abc"], target: nodes["def"]},
{source: nodes["abc"], target: nodes["ghi"]},
{source: nodes["def"], target: nodes["jkl"]}
]

但得到这个错误:

未捕获的类型错误:无法读取未定义的属性“x”

这里:

link.attr("x1", function(d)   { return d.source.x; })

这里是完整的代码:

<!doctype html>
<html>

<head>

    <title>D3 tutorial</title>
    <script src="https://d3js.org/d3.v3.min.js"></script>

</head>


<body>

<script>

var w = 4000,
    h = 4000;

var circleWidth = 5;

var fontFamily = 'Bree Serif',
    fontSizeHighlight = '1.5em',
    fontSizeNormal = '1em';

var palette = {
      "lightgray": "#819090",
      "gray": "#708284",
      "mediumgray": "#536870",
      "darkgray": "#475B62",

      "darkblue": "#0A2933",
      "darkerblue": "#042029",

      "paleryellow": "#FCF4DC",
      "paleyellow": "#EAE3CB",
      "yellow": "#A57706",
      "orange": "#BD3613",
      "red": "#D11C24",
      "pink": "#C61C6F",
      "purple": "#595AB7",
      "blue": "#2176C7",
      "green": "#259286",
      "yellowgreen": "#738A05"
  }

    var nodes = [
    {"name": "abc", "type": "Db"},
    {"name": "def", "type": "Db"},
    {"name": "ghi", "type": "Db"},
    {"name": "jkl", "type": "Db"}
    ]

    var links = [
    {source: nodes["abc"], target: nodes["def"]},
    {source: nodes["abc"], target: nodes["ghi"]},
    {source: nodes["def"], target: nodes["jkl"]}
    ]



var vis = d3.select("body")
    .append("svg:svg")
      .attr("class", "stage")
      .attr("width", w)
      .attr("height", h);

var force = d3.layout.force()
    .nodes(nodes)
    .links([])
    .gravity(0.1)
    .charge(-1000)
    .size([w, h]);

 var link = vis.selectAll(".link")
        .data(links)
        .enter().append("line")
          .attr("class", "link")
          .attr("stroke", "#CCC")
          .attr("fill", "none");

 var node = vis.selectAll("circle.node")
      .data(nodes)
      .enter().append("g")
      .attr("class", "node")

      //MOUSEOVER
      .on("mouseover", function(d,i) {
        if (i>0) {
          //CIRCLE
          d3.select(this).selectAll("circle")
          .transition()
          .duration(250)
          .style("cursor", "none")     
          .attr("r", circleWidth+3)
          .attr("fill",palette.black);

          //TEXT
          d3.select(this).select("text")
          .transition()
          .style("cursor", "none")     
          .duration(250)
          .style("cursor", "none")     
          .attr("font-size","1.5em")
          .attr("x", 15 )
          .attr("y", 5 )
          .text(function(d) { return d.name + "_" + d.type; })
        } else {
          //CIRCLE
          d3.select(this).selectAll("circle")
          .style("cursor", "none")     

          //TEXT
          d3.select(this).select("text")
          .style("cursor", "none")     
        }
      })

      //MOUSEOUT
      .on("mouseout", function(d,i) {
        if (i>0) {
          //CIRCLE
          d3.select(this).selectAll("circle")
          .transition()
          .duration(250)
          .attr("r", circleWidth)
          .attr("fill",palette.pink);

          //TEXT
          d3.select(this).select("text")
          .transition()
          .duration(250)
          .attr("font-size","1em")
          .attr("x", 8 )
          .attr("y", 4 )
          .text(function(d) { return d.name; })
        }
      })

      .call(force.drag);


    //CIRCLE
    node.append("svg:circle")
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; })
      .attr("r", circleWidth)
      .attr("fill", function(d, i) { if (i>0) { return  palette.pink; } else { return palette.black } } )

    //TEXT
    node.append("text")
      .text(function(d, i) { return d.name; })
      .attr("x",            function(d, i) { if (i>0) { return circleWidth + 5; }   else { return -10 } })
      .attr("y",            function(d, i) { if (i>0) { return circleWidth + 0 }    else { return 8 } })
      .attr("font-family",  "Bree Serif")
      .attr("fill",         function(d, i) { if (i>0) { return  palette.black; }        else { return palette.black } })
      .attr("font-size",    function(d, i) { if (i>0) { return  "1em"; }            else { return "1.8em" } })
      .attr("text-anchor",  function(d, i) { if (i>0) { return  "beginning"; }      else { return "end" } })



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

   link.attr("x1", function(d)   { return d.source.x; })
       .attr("y1", function(d)   { return d.source.y; })
       .attr("x2", function(d)   { return d.target.x; })
       .attr("y2", function(d)   { return d.target.y; })
});

force.start();


    </script>

</body>




</html>

【问题讨论】:

标签: javascript d3.js


【解决方案1】:

使节点成为一个对象,每个名称作为一个属性/键:

var nodes = { 
    abc: {"name": "abc", "type": "Db"}, 
    def: {"name": "def", "type": "Db"}, 
    ghi: {"name": "ghi", "type": "Db"}, 
    jkl: {"name": "jkl", "type": "Db"} 
}

数组只能通过索引访问(即数组[3]),对象只能通过属性访问(即object["propertyName"]object.propertyName .

【讨论】:

【解决方案2】:

它返回undefined,因为方括号内的数字是数组中对象(在这种特殊情况下)的索引。当您使用nodes[0] 时,您将引用数组nodes 中的第一个对象(索引从零开始,即0 是第一个对象,1 是第二个对象,依此类推)。

如果您想引用键 name 的值为“abc”的对象,您必须先找到它。请看这个答案:

How to get index of object by its property in javascript

【讨论】:

    猜你喜欢
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多