Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I want to distinguish the link of d3.js force graph by the thickness

I want to distinguish the link by the thickness.

I have the data.

The variable "value" means "thickness".

The range of "value" is 0~1.

    {"nodes":[{"name":"A", "group":1},
              {"name":"B", "group":1},
              {"name":"C", "group":1},
              {"name":"D", "group":1},
              {"name":"E", "group":1}],
     "links":[{"source":0,"target":1,"value":0.9},
              {"source":0,"target":2,"value":0.8},
              {"source":0,"target":3,"value":0.7},
              {"source":1,"target":2,"value":0.7},
              {"source":2,"target":4,"value":0.2},
              {"source":0,"target":4,"value":0.5}]}

And my d3.js graph code is

    <!DOCTYPE html>
    <meta charset="utf-8">

    <body><script src="../d3-master/d3.min.js"></script>
    <head><link rel="stylesheet" type="text/css" href="../D3css/D3css.css"></head>

    <script>

    var width = 960,
        height = 500

    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);

    var force = d3.layout.force()
        .gravity(.05)
        .distance(100)
        .charge(-100)
        .size([width, height]);

    d3.json("../data/cor_test.json", function(error, json) {

      force
        .nodes(json.nodes)
        .links(json.links)
        .start();

      var link = svg.selectAll(".link")
          .data(json.links)
        .enter().append("line")
          .attr("class", "link");

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

      node.append("circle")
          .attr("r", 5);

      node.append("text")
          .attr("dx", 12)
          .attr("dy", ".35em")
          .text(function(d) { return d.name });

      force.on("tick", function() {
        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; });

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

    </script>

I changed the code like this.

but it doesn't work.

      var link = svg.selectAll(".link")
          .data(json.links)
        .enter().append("line")
          .attr("class", "link")
          .attr("stroke-width", function(d) { return d.value; });

More simply change : .attr("stroke-width", "5px"); doesn't work too.

The link didn't show.

What should I do?

like image 498
user3766479 Avatar asked Jul 11 '14 07:07

user3766479


2 Answers

You need to specify the 'stroke' attribute first, because:

The default value for the stroke attribute is none which means that the outline is never drawn.

See the documentation for stroke. Below is an example of how it might be done:

selection
    .attr('stroke', 'red')
    .attr('stroke-width', 5);

Here's a jsfiddle demonstrating how it works.

like image 135
Oleg Avatar answered Oct 31 '22 04:10

Oleg


I believe @Oleg 's answer is complete and right on, however, I just want to bring to your attention an example that makes extensive use of link thicknesses, and other related svg attributes:

2013 Budget Visualization

enter image description here

Relevant code is here:

        // Enter any new links at the parent's previous position.
    link.enter().insert("svg:path", "g")
            .attr("class", "link")
            .attr("d", function(d) {
                if (Number(d.target[spendField]) > 0) {
                    var o = {x: source.x0, y: source.y0};
                    return diagonal({source: o, target: o});
                }
                else {
                    null;
                }
            })
            .style("stroke",function (d,i) {
                if (d.source.depth==0) {
                    rootCounter++;
                    return (d.source.children[rootCounter-1].linkColor);
                }
                else {
                    return (d.source) ? d.source.linkColor : d.linkColor;
                }
            })
            .style("stroke-width", function (d,i) {

                if (d.source.depth==0) {
                    var ret = level1Radius(d.target[spendField]) * 2;
                    return (isNaN(ret) ? 4 : ret);
                }
                else if (d.source.depth==1) {
                    var ret = level2Radius(d.target[spendField]) * 2;
                    return (isNaN(ret) ? 4 : ret);
                }
                else if (d.source.depth==2) {
                    var ret = level3Radius(d.target[spendField]) * 2;
                    return (isNaN(ret) ? 4 : ret);
                }
                else if (d.source.depth==3) {
                    var ret = level4Radius(d.target[spendField]) * 2;
                    return (isNaN(ret) ? 4 : ret);
                }
             })
            .style("stroke-opacity", function(d){
                var ret = ((d.source.depth+1)/4.5)
                if (d.target[spendField] <= 0) ret=.1;
                return ret;
            })
            .style("stroke-linecap","round")
            .transition()
            .duration(duration);
      //      .attr("d", diagonal);


    // Transition links to their new position.
     var linkUpdate = link.transition()
            .duration(duration)
            .attr("d", diagonal);

     linkUpdate
             .style("stroke-width", function (d,i) {
                 if (d.source.depth==0) {
                     var ret = level1Radius(Number(d.target[spendField])) * 2;
                     return (isNaN(ret) ? 4 : ret);
                 }
                 else if (d.source.depth==1) {
                     var ret = level2Radius(Number(d.target[spendField])) * 2;
                     return (isNaN(ret) ? 4 : ret);
                 }
                 else if (d.source.depth==2) {
                     var ret = level3Radius(Number(d.target[spendField])) * 2;
                     return (isNaN(ret) ? 4 : ret);
                 }
                 else if (d.source.depth==3) {
                     var ret = level4Radius(Number(d.target[spendField])) * 2;
                     return (isNaN(ret) ? 4 : ret);
                 }
            })
         //    .style("stroke-dasharray", function(d) {
         //       var ret=(d.target[spendField] > 0) ? "" : "5,8";
         //       return ret;
         //    })
             .style("stroke-opacity", function(d){
                 var ret = ((d.source.depth+1)/4.5)
                 if (d.target[spendField] <= 0) ret=.1;
                 return ret;
             })


    // Transition exiting nodes to the parent's new position.
    link.exit().transition()
            .duration(duration)
            .attr("d", diagonal)
            .remove();

Besides usage of stroke, stroke-width, you can notice usage of stroke-opacity, stroke-linecap, and general enter/update/exit pattern.

Hope this helps.

like image 41
VividD Avatar answered Oct 31 '22 04:10

VividD