如何标记节点并在D3中创建箭头?

时间:2017-10-25 19:22:16

标签: javascript d3.js graph

我希望节点具有标签,并且线条是指向节点边缘的箭头。我也希望重量在边缘。我是D3的新手,在找到这样做的例子时遇到了麻烦。大多数示例图是强制定向的,或创建定向图。我想制作一种非交互式的路径图。

基本上,我希望源节点指向目标节点。我只想在d3中绘制这个图。我觉得这很简单,但我似乎无法弄明白。有什么建议?

<div id="graph">
<script>

var vis = d3.select("#graph")
            .append("svg")
            .attr("width", 1000)
            .attr("height", 1000);

var nodes = [
   {label: "Social Dominance", x: 300, y:400},
   {label: "Gender Identification", x: 500, y: 200},
   {label: "Hostile Sexism", x:500, y:600},
   {label: "Collactive Action", x:700, y:400}

   ], 
    edges =[
   {source: nodes[0], target: nodes[1], weight: 0},
   {source: nodes[0], target: nodes[2], weight: 0},
   {source: nodes[0], target: nodes[3], weight: 0},
   {source: nodes[1], target: nodes[3], weidht: 0},
   {source: nodes[2], target: nodes[3], weight: 0}
   ];

vis.selectAll("circle.nodes")
     .data(nodes)
     .enter()
     .append("svg:circle")
     .attr("cx", function(d) { return d.x; })
     .attr("cy", function(d) { return d.y; })
     .attr("r", "60px")
     .attr("fill", "pink");


vis.selectAll("line")
    .data(edges)  
    .enter()
    .append("line")
    .attr("id", function(d,i){return 'edge'})
    .attr('marker-end', 'url(#arrowhead)')
    .style("stroke", "#ccc");

vis.selectAll(".nodelabel")
    .data(nodes)
    .enter()
    .append("text")
    .attr({"cx":function(d){return d.x;},
              "cy":function(d){return d.y;},
              "class":"nodelabel",
              "stroke":"black"})
    .text(function(d){return d.name;});

vis.selectAll(".edgepath")
        .data(edges)
        .enter()
        .append('path')
        .attr({'d': function(d) {return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y},
               'class':'edgepath',
               'fill-opacity':100,
               'stroke-opacity':100,
               'fill':'blue',
               'stroke':'black',
               'id':function(d,i) {return 'edgepath'+i}});

vis.append('defs').append('marker')
    .attr({'id':'arrowhead',
            'viewBox':'-0 -5 10 10',
            'refX':25,
            'refY':0,
        //'markerUnits':'strokeWidth',
            'orient':'auto',
            'markerWidth':100,
            'markerHeight':100,
            'xoverflow':'visible'})
    .append('svg:path')
        .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
        .attr('fill', '#ccc')
        .attr('stroke','#ccc');

</script>
</div>  

1 个答案:

答案 0 :(得分:0)

您需要对代码进行一些更改。以下是摘要:

  1. 文字没有cxcy属性。它们应为xy;
  2. 文字属性为label,而非name;
  3. 您必须将标记设置为<path>元素,而不是<line>元素;
  4. 更改标记属性以更好地适应圆圈的边缘。
  5. 以下是包含这些更改的代码:

    &#13;
    &#13;
    <script src="https://d3js.org/d3.v3.min.js"></script>
    <div id="graph">
      <script>
        var vis = d3.select("#graph")
          .append("svg")
          .attr("width", 1000)
          .attr("height", 1000);
    
        var nodes = [{
            label: "Social Dominance",
            x: 300,
            y: 400
          }, {
            label: "Gender Identification",
            x: 500,
            y: 200
          }, {
            label: "Hostile Sexism",
            x: 500,
            y: 600
          }, {
            label: "Collactive Action",
            x: 700,
            y: 400
          }],
          edges = [{
            source: nodes[0],
            target: nodes[1],
            weight: 0
          }, {
            source: nodes[0],
            target: nodes[2],
            weight: 0
          }, {
            source: nodes[0],
            target: nodes[3],
            weight: 0
          }, {
            source: nodes[1],
            target: nodes[3],
            weidht: 0
          }, {
            source: nodes[2],
            target: nodes[3],
            weight: 0
          }];
    
        vis.selectAll(".edgepath")
          .data(edges)
          .enter()
          .append('path')
          .attr({
            'd': function(d) {
              return 'M ' + d.source.x + ' ' + d.source.y + ' L ' + d.target.x + ' ' + d.target.y
            },
            'class': 'edgepath',
            'fill-opacity': 100,
            'stroke-opacity': 100,
            'fill': 'blue',
            'stroke': 'black',
            'marker-end': 'url(#arrowhead)',
            'id': function(d, i) {
              return 'edgepath' + i
            }
          });
    
        vis.selectAll("circle.nodes")
          .data(nodes)
          .enter()
          .append("svg:circle")
          .attr("cx", function(d) {
            return d.x;
          })
          .attr("cy", function(d) {
            return d.y;
          })
          .attr("r", "60px")
          .attr("fill", "pink");
    
        vis.selectAll(".nodelabel")
          .data(nodes)
          .enter()
          .append("text")
          .attr({
            "x": function(d) {
              return d.x;
            },
            "y": function(d) {
              return d.y;
            },
            "class": "nodelabel",
            "text-anchor": "middle",
            "fill": "black"
          })
          .text(function(d) {
            return d.label;
          });
    
        vis.append('defs').append('marker')
          .attr({
            'id': 'arrowhead',
            'viewBox': '-0 -5 10 10',
            'refX': 70,
            'refY': 0,
            //'markerUnits':'strokeWidth',
            'orient': 'auto',
            'markerWidth': 10,
            'markerHeight': 10,
            'xoverflow': 'visible'
          })
          .append('svg:path')
          .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
          .attr('fill', '#aaa')
          .attr('stroke', '#aaa');
    
      </script>
    </div>
    &#13;
    &#13;
    &#13;