title: d3.js - connecting shapes with lines (without using force or other layouts)
body: <p>I have a bunch of static circles and I want to connect them with lines (it's a dependency graph). All the examples I see are done with d3's ready-made layouts and I'm not sure how to approach this efficiently. I also want to highlight lines related to a node when I mouse-over that node, as well as fade any other shapes/lines.</p>
  
  <p>This is what I have for now: (it just draws evenly spaced and sized circles according to area size given)</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
      &lt;script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"&gt;&lt;/script&gt;
  &lt;/head&gt;
  &lt;body style="overflow: hidden;"&gt;
       &lt;div id="drawarea"  style="overflow: hidden;"&gt;&lt;/div&gt;
  
     &lt;script type="text/javascript"&gt;
  
  
  var dataset = [],
      i = 0;
  
  for(i=0; i&lt;45; i++){
      dataset.push(Math.round(Math.random()*100));
  }    
  
   var   width = 5000,
         height = 3000;
  
  var svg = d3.select("#drawarea").append("svg")
      .attr("width", width)
      .attr("height", height)
      .call(d3.behavior.zoom().scaleExtent([1, 8]).on("zoom", zoom))
    .append("g");
  
  var div_area = width*height,
      num_nodes = dataset.length,
      node_area = div_area/num_nodes*0.7,
      node_to_padding_ratio = 0.50,
      node_dia_inc_pad = Math.sqrt(node_area),
      node_radius_wo_pad = node_dia_inc_pad/2*node_to_padding_ratio,
      node_padding = node_dia_inc_pad/2*(1-node_to_padding_ratio),
      nodes_in_width = parseInt(width/(node_dia_inc_pad)),
      nodes_in_height = parseInt(height/(node_dia_inc_pad));  
  
  svg.selectAll("circle")
      .data(dataset)
      .enter().append("circle")
      .style("stroke", "gray")
      .style("fill", "white")
      .attr("r", node_radius_wo_pad)
      .attr("cx", function(d, i){ return 2*node_radius_wo_pad+i%nodes_in_width*node_dia_inc_pad;})
      .attr("cy", function(d, i){ return 2*node_radius_wo_pad+(parseInt(i/nodes_in_width))*node_dia_inc_pad})
      .on("mouseover", function(){d3.select(this).style("fill", "aliceblue");})
      .on("mouseout", function(){d3.select(this).style("fill", "white");})
  
  function zoom() {
    svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
  }
  
      &lt;/script&gt;     
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p><strong>EDIT:</strong> My revised code:</p>
  
  <pre><code>    &lt;!DOCTYPE html&gt;
      &lt;html&gt;
      &lt;head&gt;
          &lt;script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"&gt;&lt;/script&gt;
      &lt;/head&gt;
      &lt;body style="overflow: hidden;"&gt;
           &lt;div id="canvas"  style="overflow: hidden;"&gt;&lt;/div&gt;
  
         &lt;script type="text/javascript"&gt;
      var graph = {
        "nodes":[
          {"name":"Myriel","group":1},
          {"name":"Napoleon","group":1}
        ],
        "links":[
          {"source":1,"target":0,"value":1}
        ]
      }
  
  
        var   width = 2000,
         height = 1000;
  
  var svg = d3.select("#canvas").append("svg")
      .attr("width", width)
      .attr("height", height)
      .call(d3.behavior.zoom().scaleExtent([1, 8]).on("zoom", zoom))
    .append("g");
  
  
  
  var div_area = width*height,
      num_nodes = graph.nodes.length,
      node_area = div_area/num_nodes,
      node_to_padding_ratio = 0.50,
      node_dia_inc_pad = Math.sqrt(node_area),
      node_radius_wo_pad = node_dia_inc_pad/2*node_to_padding_ratio,
      node_padding = node_dia_inc_pad/2*(1-node_to_padding_ratio),
      nodes_in_width = parseInt(width/(node_dia_inc_pad)),
      nodes_in_height = parseInt(height/(node_dia_inc_pad));  
  
  
  var xScale = d3.scale.linear()
      .domain([0,nodes_in_width])
      .range([node_radius_wo_pad,width-node_radius_wo_pad]);
  
  var yScale = d3.scale.linear()
      .domain([0,nodes_in_height])
      .range([node_radius_wo_pad,height-node_radius_wo_pad]);
  
  
  var lines = svg.attr("class", "line")
    .selectAll("line").data(graph.links)
    .enter().append("line")
    .attr("x1", function(d) { return xScale(d.source%nodes_in_width); })
    .attr("y1", function(d) { return yScale(parseInt(d.source/nodes_in_width)); })
    .attr("x2", function(d) { return xScale(d.target%nodes_in_width); })
    .attr("y2", function(d) {  return yScale(parseInt(d.target/nodes_in_width)); })
    .attr("src", function(d) {  return d.source; })
    .attr("trgt", function(d) {  return d.target; })
    .style("stroke", "grey");
  
  var circles = svg.selectAll("circle")
      .data(graph.nodes)
      .enter().append("circle")
      .style("stroke", "gray")
      .style("fill", "white")
      .attr("r", node_radius_wo_pad)
      .attr("cx", function(d, i){ return xScale(i%nodes_in_width);})
      .attr("cy", function(d, i){ return yScale(parseInt(i/nodes_in_width));})
      .attr("index", function(d, i){return i;})
      .on("mouseover", function(){
          var that = this;
          lines.filter(function() {   
              return d3.select(this).attr("src") == d3.select(that).attr("index");
             }).style("stroke", "red");
          lines.filter(function() {
              return d3.select(this).attr("trgt") == d3.select(that).attr("index");
             }).style("stroke", "green");
          lines.filter(function() {
              return (d3.select(this).attr("trgt") != d3.select(that).attr("index") &amp;&amp; d3.select(this).attr("src") != d3.select(that).attr("index"));
             }).style("display", "none");
          d3.select(this).style("fill", "aliceblue");
       })
      .on("mouseout", function(){
        lines.style("stroke", "grey")
             .style("display", "block");
        d3.select(this).style("fill", "white");
      });
  
  
  
  
  
  
  function zoom() {
        svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
      }
      &lt;/script&gt;     
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>What I want to do now is have the circles the lines point to and from be colored similarly. I'm not sure how to make the reference to them from the "mouseover" event of a circle though. Will do some testing...</p>