Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make force layout graph in D3.js responsive to screen/browser size

The problem is not within .size(), it's that you are stating the SVG dimensions in .attr("width", w) .attr("height", h). Remove these two attributes and you'll get it right...

var svg = d3.select("#viz").append("svg")
            .attr("id", "playgraph")
             //better to keep the viewBox dimensions with variables
            .attr("viewBox", "0 0 " + w + " " + h )
            .attr("preserveAspectRatio", "xMidYMid meet");

http://jsfiddle.net/aaSjd/


The solution shown here: http://bl.ocks.org/mbostock/3355967 worked well for me!

window.addEventListener('resize', resize); 

function resize() {
    var width = window.innerWidth, height = window.innerHeight;
    svg.attr("width", width).attr("height", height);
    force.size([width, height]).resume();
}

Make sure to run resize() after you have appended all your lines, nodes etc as well.


Duopixel is very close to what I needed, except I don't know why he nested two <g> elements and attached the event listeners to the outermost <g> (also requiring an invisible rectangle behind everything to make the g react to events over its whole space).

It's easier to attach the listeners to the <svg> itself and then you only need one internal <g>.

Here is my full-screen force-directed example:

var width = 1000,
    height = 1000;

var color = d3.scale.category20();

var svg = d3.select("body")
    .append("svg")
      .attr({
        "width": "100%",
        "height": "100%"
      })
      .attr("viewBox", "0 0 " + width + " " + height )
      .attr("preserveAspectRatio", "xMidYMid meet")
      .attr("pointer-events", "all")
    .call(d3.behavior.zoom().on("zoom", redraw));

var vis = svg
    .append('svg:g');

function redraw() {
  vis.attr("transform",
      "translate(" + d3.event.translate + ")"
      + " scale(" + d3.event.scale + ")");
}

function draw_graph(graph) {
  var force = d3.layout.force()
      .charge(-120)
      .linkDistance(30)
      .nodes(graph.nodes)
      .links(graph.links)
      .size([width, height])
      .start();

  var link = vis.selectAll(".link")
      .data(graph.links)
      .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = vis.selectAll(".node")
      .data(graph.nodes)
      .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag);

  node.append("title")
      .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("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  });
};

draw_graph(data);