Resize svg lorsque window est redimensionné en d3.js
je dessine un scatterplot avec d3.js. Avec l'aide de cette question :
obtenez la taille de l'écran, la page Web actuelle et la fenêtre du navigateur
j'utilise cette réponse:
var w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName('body')[0],
x = w.innerWidth || e.clientWidth || g.clientWidth,
y = w.innerHeight|| e.clientHeight|| g.clientHeight;
donc je suis capable d'ajuster mon intrigue à la fenêtre de l'utilisateur comme ceci:
var svg = d3.select("body").append("svg")
.attr("width", x)
.attr("height", y)
.append("g");
maintenant, j'aimerais que quelque chose prenne soin de redimensionner la parcelle quand l'utilisateur redimensionne la fenêtre.
PS: je n'utilise pas jQuery dans mon code.
6 réponses
chercher 'responsive SVG' il est assez simple de rendre un SVG responsive et vous n'avez plus à vous soucier des tailles.
Voici comment je l'ai fait:
d3.select("div#chartId")
.append("div")
.classed("svg-container", true) //container class to make it responsive
.append("svg")
//responsive SVG needs these 2 attributes and no width and height attr
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 600 400")
//class to make it responsive
.classed("svg-content-responsive", true);
le code CSS:
.svg-container {
display: inline-block;
position: relative;
width: 100%;
padding-bottom: 100%; /* aspect ratio */
vertical-align: top;
overflow: hidden;
}
.svg-content-responsive {
display: inline-block;
position: absolute;
top: 10px;
left: 0;
}
plus d'info / tutoriels:
http://thenewcode.com/744/Make-SVG-Responsive
http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php
utiliser" fenêtre 151920920".onrésize :
function updateWindow(){
x = w.innerWidth || e.clientWidth || g.clientWidth;
y = w.innerHeight|| e.clientHeight|| g.clientHeight;
svg.attr("width", x).attr("height", y);
}
d3.select(window).on('resize.updatesvg', updateWindow);
mise à jour il suffit d'utiliser la nouvelle voie de @cminatti
vieille réponse à des fins d'historique
IMO il est préférable d'utiliser select() et on () puisque de cette façon vous pouvez avoir plusieurs gestionnaires d'événements redimensionner... il suffit de ne pas se prendre la tête
d3.select(window).on('resize', resize);
function resize() {
// update width
width = parseInt(d3.select('#chart').style('width'), 10);
width = width - margin.left - margin.right;
// resize the chart
x.range([0, width]);
d3.select(chart.node().parentNode)
.style('height', (y.rangeExtent()[1] + margin.top + margin.bottom) + 'px')
.style('width', (width + margin.left + margin.right) + 'px');
chart.selectAll('rect.background')
.attr('width', width);
chart.selectAll('rect.percent')
.attr('width', function(d) { return x(d.percent); });
// update median ticks
var median = d3.median(chart.selectAll('.bar').data(),
function(d) { return d.percent; });
chart.selectAll('line.median')
.attr('x1', x(median))
.attr('x2', x(median));
// update axes
chart.select('.x.axis.top').call(xAxis.orient('top'));
chart.select('.x.axis.bottom').call(xAxis.orient('bottom'));
}
http://eyeseast.github.io/visible-data/2013/08/28/responsive-charts-with-d3 /
c'est un peu moche si le code de redimensionnement est presque aussi long que le code pour construire le graphe en premier lieu. Donc, au lieu de redimensionner chaque élément du diagramme existant, pourquoi ne pas simplement le recharger? Voici comment cela a fonctionné pour moi:
function data_display(data){
e = document.getElementById('data-div');
var w = e.clientWidth;
// remove old svg if any -- otherwise resizing adds a second one
d3.select('svg').remove();
// create canvas
var svg = d3.select('#data-div').append('svg')
.attr('height', 100)
.attr('width', w);
// now add lots of beautiful elements to your graph
// ...
}
data_display(my_data); // call on page load
window.addEventListener('resize', function(event){
data_display(my_data); // just call it again...
}
la ligne cruciale est d3.select('svg').remove(); . Sinon, chaque redimensionnement ajoutera un autre élément SVG sous le précédent.
layouts en vigueur le simple fait de définir les attributs 'height' et 'width' ne fonctionnera pas pour recentrer/déplacer la parcelle dans le conteneur svg. Cependant, il y a une réponse très simple qui fonctionne pour les dispositions de Force trouvées ici . En résumé:
utilisez le même (tous) même si vous aimez.
window.on('resize', resize);
en supposant que vous avez les variables svg & force:
var svg = /* D3 Code */;
var force = /* D3 Code */;
function resize(e){
// get width/height with container selector (body also works)
// or use other method of calculating desired values
var width = $('#myselector').width();
var height = $('#myselector').height();
// set attrs and 'resume' force
svg.attr('width', width);
svg.attr('height', height);
force.size([width, height]).resume();
}
de cette façon, vous ne graphique entièrement, nous définissons les attributs et d3 calcule les choses comme nécessaire. Ce qui fonctionne lorsque vous utilisez un point de gravité. Je ne suis pas sûr que ce soit une condition préalable pour cette solution. Quelqu'un peut-il confirmer ou infirmer ?
Cheers, g
j'utilise la fenêtre.innerWidth pour la largeur et la fenêtre du client.hauteur intérieure pour la hauteur du client.