242 votes

Quel est le meilleur moyen de faire un d3.js visualisation de mise en page responsive?

Supposons que j'ai un histogramme script qui construit un 960 500 svg graphiques. Comment puis-je faire de ce réactif donc sur redimensionner le graphique largeurs et hauteurs sont dynamiques?

<script> 

var n = 10000, // number of trials
    m = 10,    // number of random variables
    data = [];

// Generate an Irwin-Hall distribution.
for (var i = 0; i < n; i++) {
  for (var s = 0, j = 0; j < m; j++) {
    s += Math.random();
  }
  data.push(s);
}

var histogram = d3.layout.histogram()
    (data);

var width = 960,
    height = 500;

var x = d3.scale.ordinal()
    .domain(histogram.map(function(d) { return d.x; }))
    .rangeRoundBands([0, width]);

var y = d3.scale.linear()
    .domain([0, d3.max(histogram.map(function(d) { return d.y; }))])
    .range([0, height]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

svg.selectAll("rect")
    .data(histogram)
  .enter().append("rect")
    .attr("width", x.rangeBand())
    .attr("x", function(d) { return x(d.x); })
    .attr("y", function(d) { return height - y(d.y); })
    .attr("height", function(d) { return y(d.y); });

svg.append("line")
    .attr("x1", 0)
    .attr("x2", width)
    .attr("y1", height)
    .attr("y2", height);

</script> 

Exemple complet de l'histogramme de gist est: https://gist.github.com/993912

347voto

Shawn Allen Points 2309

Il y a une autre façon de faire qui ne nécessite pas de redessiner le graphique, et il implique la modification de la viewBox et preserveAspectRatio attributs sur l' <svg> élément:

<svg id="chart" width="960" height="500"
  viewBox="0 0 960 500"
  preserveAspectRatio="xMidYMid">
</svg>

Alors, si vous dessinez votre graphique au sein de l' (960, 500) limites, tout ce que vous avez à faire est de redimensionner l' <svg> élément:

var aspect = 960 / 500,
    chart = $("#chart");
$(window).on("resize", function() {
    var targetWidth = chart.parent().width();
    chart.attr("width", targetWidth);
    chart.attr("height", targetWidth / aspect);
});

Et le svg contenu sera mis à l'échelle automatiquement. Vous pouvez voir un exemple de ceci (avec quelques modifications) ici: il suffit de redimensionner la fenêtre ou le volet inférieur droit pour voir comment il réagit.

36voto

cminatti Points 378

Recherchez le responsive SVG', il est assez simple de faire un SVG réactive et vous n'avez pas à vous soucier de tailles de plus.

Voici comment j'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'infos / tutos:

http://demosthenes.info/blog/744/Make-SVG-Responsive

http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php

21voto

Matt Alcock Points 1913

J'ai codé un petit résumé de résoudre ce problème.

La solution générale motif est ceci:

  1. Breakout le script dans le calcul et les fonctions de dessin.
  2. Assurer la fonction de dessin dessine de façon dynamique et est conduit de visualisation de largeur et de hauteur variables (La meilleure façon de le faire est l'utilisation de la d3.à l'échelle de l'api)
  3. Bind/chaîne le dessin d'une référence de l'élément dans les balises. (J'ai utilisé jquery pour cela, donc importé).
  4. N'oubliez pas de le supprimer si il est déjà établi. Obtenir les dimensions de l'élément référencé à l'aide de jquery.
  5. Bind/chaîne la fonction draw à la fenêtre de la fonction de redimensionnement. Introduire un anti-rebond (timeout) pour ce chaîne pour nous assurer de seulement redessiner après un délai d'attente.

J'ai aussi ajouté le minifiés d3.js script pour la vitesse. L'essentiel est ici: https://gist.github.com/2414111

jquery référence code:

$(reference).empty()
var width = $(reference).width();

Antirebond de code:

var debounce = function(fn, timeout) 
{
  var timeoutID = -1;
  return function() {
     if (timeoutID > -1) {
        window.clearTimeout(timeoutID);
     }
   timeoutID = window.setTimeout(fn, timeout);
  }
};

var debounced_draw = debounce(function() {
    draw_histogram(div_name, pos_data, neg_data);
  }, 125);

 $(window).resize(debounced_draw);

Profitez-en!

-2voto

arlindmusliu Points 15

Vous pouvez également utiliser bootstrap 3 pour s'adapter à la taille d'une visualisation. Par exemple, nous pouvons mettre en place le HTML code:

<div class="container>
<div class="row">

<div class='col-sm-6 col-md-4' id="month-view" style="height:345px;">
<div id ="responsivetext">Something to write</div>
</div>

</div>
</div>

J'ai mis en place une hauteur fixe à cause de mes besoins, mais vous pouvez laisser la taille de l'auto. Le "col-sm-6 col-md-4" rend la div sensible pour les différents appareils. Vous pouvez en apprendre davantage au http://getbootstrap.com/css/#grid-example-basic

Nous pouvons accéder à la graphique avec l'aide de l'id de la vue mensuelle.

Je ne vais pas entrer dans beaucoup de détails sur les d3 code, je vais d'entrée seulement la partie qui est nécessaire pour s'adapter aux différentes tailles d'écran.

var width = document.getElementById('month-view').offsetWidth;

var height = document.getElementById('month-view').offsetHeight - document.getElementById('responsivetext2').offsetHeight;

La largeur est définie par obtenir la largeur de la div avec l'id de la vue mensuelle.

La hauteur dans mon cas ne doit pas inclure l'ensemble de la zone. J'ai aussi un peu de texte au-dessus de la barre, donc j'ai besoin de calculer ce domaine. C'est pourquoi j'ai identifié la zone de texte avec l'id responsivetext. Pour le calcul de la permis à la hauteur de la barre, j'ai soustrait la hauteur du texte à partir de la hauteur de la div.

Cela vous permet d'avoir une barre qui adopte l'ensemble de l'écran/div tailles. Il pourrait ne pas être la meilleure façon de le faire, mais elle a sûrement des œuvres pour les besoins de mon projet.

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