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.

156
demandé sur Community 2013-04-28 20:37:32

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

246
répondu cminatti 2016-08-28 10:53:41

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

http://jsfiddle.net/Zb85u/1 /

40
répondu Adam Pearce 2016-11-15 23:46:59

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 /

32
répondu slf 2016-03-15 16:45:36

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.

12
répondu Raik 2014-05-03 02:46:21

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

8
répondu gavs 2014-05-12 21:31:41

j'utilise la fenêtre.innerWidth pour la largeur et la fenêtre du client.hauteur intérieure pour la hauteur du client.

0
répondu Akshay 2018-08-24 17:38:14