d3.js: How do I draw and highlight links in this relationship graph? -
i've been trying solve graph problem couple weeks now... still pretty new d3.js, things seem might simple still elude me.
here's illustration of i'm trying do:

the goals:
i want show relationships between industry nodes/size nodes , product nodes.
when hover product node, want highlight link, source (industry or size) , target (product) of each relevant relationship.
when hover industry or size node, want highlight it's links relevant products.
the questions
how draw links? know somehow involves using d3.map... can't figure out.
how highlight nodes , links (goals 2 , 3)?
if there better, more efficient way of getting layout , behavior, please let me know - trying hard learn tricks!
the fiddle renders basic layout simplified set of data: http://jsfiddle.net/9hgbd/
the data looks this:
    var data = {     "product": [         {             "type": "product",             "name": "product 1"         },         {             "type": "product",             "name": "product 2"         },         {             "type": "product",             "name": "product 3"         },         {             "type": "product",             "name": "product 4"         },         {             "type": "product",             "name": "product 5"         }     ],     "industry": [          {             "type": "industry",             "name": "industry 1"         },         {             "type": "industry",             "name": "industry 2"         },         {             "type": "industry",             "name": "industry 3"         },         {             "type": "industry",             "name": "industry 4"         },         {             "type": "industry",             "name": "industry 5"         }     ],     "size": [         {             "type": "size",             "name": "size 1"         },         {             "type": "size",             "name": "size 2"         },         {             "type": "size",             "name": "size 3"         },         {             "type": "size",             "name": "size 4"         },         {             "type": "size",             "name": "size 5"         }     ],     "links": [         {             "source": "industry 1",             "target": "product 1"         },         {             "source": "industry 3",             "target": "product 1"         },         {             "source": "industry 5",             "target": "product 1"         },         {             "source": "industry 2",             "target": "product 2"         },         ...etc..     ] };   the javascript i'm using looks this:
function renderrelationshipgraph(){          var width = 800,             boxwidth = 200,             boxheight = 20,             gap = 4,             margin = {top: 16, right: 16, bottom: 16, left: 16},             height = (data.product.length * (boxheight + gap)) + margin.top + margin.bottom;          var pnodes = [];         var inodes = [];         var snodes = [];         var links = [];          data.product.foreach(function(d, i) {             d.x = ((width-margin.left-margin.right)/3)/2 - boxwidth/2;             d.y = margin.top + (boxheight+ 4)*i;             pnodes.push(d);         });          data.industry.foreach(function(d, i) {             d.x = 0;             d.y = margin.top + (boxheight+ 4)*i;              inodes.push(d);         });          data.size.foreach(function(d, i) {             d.x = ((width-margin.left-margin.right)/3) - boxwidth;             d.y = margin.top + (boxheight+ 4)*i;              snodes.push(d);         });          var svg = d3.select("#graph").append("svg")                 .attr("width", width)                 .attr("height", height)                 .append("g");          svg.append("g")                 .attr("class", "industries");           svg.append("g")                 .attr("class", "products")                 .attr("transform", "translate("+ (width-margin.left-margin.right)/3 + ", 0)");           svg.append("g")                 .attr("class", "sizes")                 .attr("transform", "translate("+ 2*((width-margin.left-margin.right)/3) + ", 0)");           var products = svg.select(".products");         var product = products.selectall("g")                 .data(pnodes)                 .enter()                 .append("g")                 .attr("class", "unit");                  product.append("rect")                 .attr("x", function(d) {return d.x;})                 .attr("y", function(d) {return d.y;})                 .attr("width", boxwidth)                 .attr("height", boxheight)                 .attr("class", "product")                 .attr("rx", 6)                 .attr("ry", 6)                 .on("mouseover", function() { d3.select(this).classed("active", true); })                 .on("mouseout", function() { d3.select(this).classed("active", false); });                  product.append("text")                 .attr("class", "label")                 .attr("x", function(d) {return d.x + 14;})                 .attr("y", function(d) {return d.y + 15;})                 .text(function(d) {return d.name;});          var industries = svg.select(".industries");         var industry = industries.selectall("g")                 .data(inodes)                 .enter()                 .append("g")                 .attr("class", "unit");                  industry.append("rect")                 .attr("x", function(d) {return d.x;})                 .attr("y", function(d) {return d.y;})                 .attr("width", boxwidth)                 .attr("height", boxheight)                 .attr("class", "industry")                 .attr("rx", 6)                 .attr("ry", 6)                 .on("mouseover", function() { d3.select(this).classed("active", true); })                 .on("mouseout", function() { d3.select(this).classed("active", false); });                  industry.append("text")                 .attr("class", "label")                 .attr("x", function(d) {return d.x + 14;})                 .attr("y", function(d) {return d.y + 15;})                 .text(function(d) {return d.name;});          var sizes = svg.select(".sizes");         var size = sizes.selectall("g")                 .data(snodes)                 .enter()                 .append("g")                 .attr("class", "unit");                  size.append("rect")                 .attr("x", function(d) {return d.x;})                 .attr("y", function(d) {return d.y;})                 .attr("width", boxwidth)                 .attr("height", boxheight)                 .attr("class", "size")                 .attr("rx", 6)                 .attr("ry", 6)                 .on("mouseover", function() { d3.select(this).classed("active", true); })                 .on("mouseout", function() { d3.select(this).classed("active", false); });                  size.append("text")                 .attr("class", "label")                 .attr("x", function(d) {return d.x + 14;})                 .attr("y", function(d) {return d.y + 15;})                 .text(function(d) {return d.name;});     }      renderrelationshipgraph();   thanks on this!
ok tried make example work since have same sort of problem. sake of posterity answering here well. maybe have same problem or finds easier solution.
 new javascript (tried learn bit in past week) may not best solution. files , result available in jsfiddle. i'll not provide whole codes , point changes.
in order able add arbitrary number of columns changed
jsonfile , replacedtypelevellvl. replacedindustriy,product,sizecategory callednodes.each rectangle , line in
svgcreated in javascript file setupidcan referred later (when changing color).
the relevant code
  data.nodes.foreach(function (d, i) {       d.x = margin.left + d.lvl * (boxwidth + gap.width);       d.y = margin.top + (boxheight + gap.height) * count[d.lvl];       d.id = "n" + i;       count[d.lvl] += 1;       nodes.push(d);   });    data.links.foreach(function (d) {       links.push({          source: find(d.source),          target: find(d.target),          id: "l" + find(d.source).id + find(d.target).id       });   });   the method find used here function finds node name passed it.
the
mouseover,mouseoutevents updated follows:.on("mouseover", function () { mouse_action(d3.select(this).datum(), true, true); }) .on("mouseout", function () { mouse_action(d3.select(this).datum(), false, true); });
it uses methods, mouse_action accepts starting node , state (active or inactive). in method visit each link, process , change state. method traverses in both directions (left , right) on node mouse entered , traverses left or right on other nodes.
function mouse_action(val, stat, direction) {     "use strict";     d3.select("#" + val.id).classed("active", stat);      links.foreach(function (d) {         if (direction == "root") {             if (d.source.id === val.id) {                 d3.select("#" + d.id).movetofront().classed("activelink", stat); // change link color                 d3.select("#" + d.id).movetofront().classed("link", !stat); // change link color                 if (d.target.lvl < val.lvl)                     mouse_action(d.target, stat, "left");                 else if (d.target.lvl > val.lvl)                     mouse_action(d.target, stat, "right");             }             if (d.target.id === val.id) {                 d3.select("#" + d.id).movetofront().classed("activelink", stat); // change link color                 d3.select("#" + d.id).movetofront().classed("link", !stat); // change link color                 if (direction == "root") {                     if(d.source.lvl < val.lvl)                         mouse_action(d.source, stat, "left");                     else if (d.source.lvl > val.lvl)                         mouse_action(d.source, stat, "right");                 }             }         }else if (direction == "left") {             if (d.source.id === val.id && d.target.lvl < val.lvl) {                 d3.select("#" + d.id).movetofront().classed("activelink", stat); // change link color                 d3.select("#" + d.id).movetofront().classed("link", !stat); // change link color                 mouse_action(d.target, stat, direction);             }             if (d.target.id === val.id && d.source.lvl < val.lvl) {                 d3.select("#" + d.id).movetofront().classed("activelink", stat); // change link color                 d3.select("#" + d.id).movetofront().classed("link", !stat); // change link color                 mouse_action(d.source, stat, direction);             }         }else if (direction == "right") {             if (d.source.id === val.id && d.target.lvl > val.lvl) {                 d3.select("#" + d.id).movetofront().classed("activelink", stat); // change link color                 d3.select("#" + d.id).movetofront().classed("link", !stat); // change link color                 mouse_action(d.target, stat, direction);             }             if (d.target.id === val.id && d.source.lvl > val.lvl) {                 d3.select("#" + d.id).movetofront().classed("activelink", stat); // change link color                 d3.select("#" + d.id).movetofront().classed("link", !stat); // change link color                 mouse_action(d.source, stat, direction);             }         }     }); }      
Comments
Post a Comment