Jak zrobić wykres układu sił w D3.js reaguje na rozmiar ekranu/przeglądarki

Mam Wykres wykorzystujący układ sił, ale ma on stałą szerokość w i wysokość h:

var svg = d3.select("#viz").append("svg")
            .attr("id", "playgraph")
            .attr("width", w)
            .attr("height", h)

var force = d3.layout.force()
              .nodes(nodes)
              .links(links)
              .charge(-1600)
              .linkDistance(45)
              .size([w, h]); 

W wyniku czego powstaje wykres svg, który nie skaluje się ani nie zmniejsza pomimo zmian rozmiaru ekranu lub okna przeglądarki. W celu poprawienia responsywności (tzn. automatycznej zmiany rozmiaru), próbowałem użyć atrybutów viewBox i preserveAspectRatio:

var svg = d3.select("#viz").append("svg")
            .attr("id", "playgraph")
            .attr("width", w)
            .attr("height", h)
            .attr("viewBox", "0, 0, 600, 400")
            .attr("preserveAspectRatio", "xMidYMid meet");

Niestety, to nie działa, ponieważ nic się nie dzieje, gdy dostosowuję rozmiar okna przeglądarki. Ciekawe czy .size([w, h]) wykresu siły ma coś do zrób to.

Proszę rzucić trochę światła na używanie atrybutów viewBox i preserveAspectRatio z wykresami układu sił.

Author: VividD, 2012-08-14

3 answers

Problem nie mieści się w .size(), chodzi o to, że podajesz wymiary SVG w .attr("width", w) .attr("height", h). Usuń te dwa atrybuty, a wszystko będzie dobrze...

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/

 52
Author: Duopixel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-14 09:01:27

Rozwiązanie pokazane tutaj: http://bl.ocks.org/mbostock/3355967 dobrze mi poszło!

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();
}

Upewnij się, że uruchomisz resize() po dodaniu wszystkich linii, węzłów itp.

 9
Author: Matt Jensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-04 16:38:47

Duopixel jest bardzo zbliżony do tego, czego potrzebowałem, ale nie wiem, dlaczego zagnieżdżał dwa <g> elementy i przyczepił słuchacze zdarzeń do zewnętrznego <g> (wymagając również niewidzialnego prostokąta za wszystkim, aby g reagowało na zdarzenia w całej swojej przestrzeni).

Łatwiej jest podłączyć słuchacze do samego <svg> i wtedy wystarczy tylko jeden wewnętrzny <g>.

Oto mój pełnoekranowy przykład użycia siły:

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);
 4
Author: aaaronic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-07 20:29:00