50 votes

Comment rendre le graphique de mise en page forcé dans D3.js sensible à la taille de l'écran / du navigateur

J'ai un graphique à l'aide de la force de mise en page, mais il a une largeur fixe w et la hauteur 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]); 

les résultats dans un graphique svg qui n'est pas à l'échelle ou à la baisse en dépit de changements dans l'écran du navigateur ou la taille de la fenêtre. Afin de le rendre réceptif (c'est à dire redimensionne automatiquement lui-même), j'ai essayé d'utiliser viewBox et preserveAspectRatio attributs:

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");

Malheureusement, cela n'a pas fonctionné comme il ne se passe rien lorsque j'ajuster la taille de la fenêtre du navigateur. Je me demande si l' .size([w, h]) de la force graphique a rien à voir avec cela.

Veuillez jeter une certaine lumière sur la façon d'utiliser viewBox et preserveAspectRatio les attributs de la force de mise en page des graphiques.

55voto

Duopixel Points 27962

Le problème n'est pas dans .size() , c'est que vous énoncez les dimensions SVG en .attr("width", w) .attr("height", h) . Supprimez ces deux attributs et vous obtiendrez le résultat souhaité ...

 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/

10voto

Matt Points 365

La solution présentée ici: http://bl.ocks.org/mbostock/3355967 a bien fonctionné pour moi!

 window.addEventListener('resize', resize); 

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

Assurez-vous d’exécuter resize () après avoir ajouté toutes vos lignes, nœuds, etc.

6voto

ahaarnos Points 157

Duopixel est très proche de ce dont j'avais besoin, sauf que je ne sais pas pourquoi il imbriqués deux <g> éléments et joint les écouteurs d'événements à l'ultrapériphériques <g> (nécessitant également un rectangle invisible derrière tout pour faire de la g réagir à des événements sur l'ensemble de l'espace).

Il est plus facile de fixer les auditeurs de l' <svg> lui-même et puis vous avez seulement besoin d'un interne, <g>.

Voici mon plein écran force dirigée exemple:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X