J'ai un graphique utilisant la disposition forcée, mais il a une largeur fixe w
et une 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]);
ce qui se traduit par un graphique svg qui ne se redimensionne pas ou ne diminue pas malgré les changements de taille de l'écran ou de la fenêtre du navigateur. Afin de le rendre réactif (c'est-à-dire qu'il se redimensionne automatiquement), j'ai essayé d'utiliser les attributs viewBox
et 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");
Malheureusement, cela n'a pas fonctionné car rien ne se passe lorsque j'ajuste la taille de la fenêtre du navigateur. Je me demande si la .size([w, h])
du graphe de force a quelque chose à voir avec cela.
Veuillez nous expliquer comment utiliser les attributs viewBox
et preserveAspectRatio
avec des graphiques de mise en forme forcée.
Le problème n'est pas dans .size()
, c'est que vous indiquez les dimensions SVG dans .attr("width", w) .attr("height", h)
. Supprimez ces deux attributs et vous aurez raison ...
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");
La solution présentée ici: http://bl.ocks.org/mbostock/3355967 a bien fonctionné pour moi!
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();
}
Assurez-vous d'exécuter resize () après avoir ajouté toutes vos lignes, nœuds, etc.
Duopixel est très proche de ce dont j'avais besoin, sauf que je ne sais pas pourquoi il a imbriqué deux <g>
éléments et attaché les écouteurs de l'événement aux éléments ultrapériphériques <g>
(nécessitant également un rectangle invisible derrière tout pour que le g réagisse aux événements sur tout son espace).
Il est plus facile d'attacher les écouteurs au <svg>
lui-même et vous n'avez besoin que d'un _ <g>
.
Voici mon exemple plein écran orienté de force:
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);