Zmień rozmiar svg, gdy okno jest zmieniane w d3.js

Rysuję scatterplot z d3.js. Z pomocą tego pytania :
Pobierz rozmiar ekranu, bieżącej strony internetowej i okna przeglądarki

Używam tej odpowiedzi:

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;

Więc jestem w stanie dopasować moją działkę do okna użytkownika w ten sposób:

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

Teraz chciałbym, aby coś zajmowało się zmianą rozmiaru wykresu, gdy użytkownik zmienia rozmiar okna.

PS: nie używam jQuery w kodzie.

Author: Community, 2013-04-28

6 answers

Poszukaj 'responsive SVG' tworzenie responsywnego SVG jest dość proste i nie musisz się już martwić o rozmiary.

Oto Jak to zrobiłem:

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

Kod 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;
}

Więcej informacji / tutoriale:

Http://thenewcode.com/744/Make-SVG-Responsive

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

 246
Author: cminatti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-28 10:53:41

Użyj okna .onresize :

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
Author: Adam Pearce,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-15 23:46:59

UPDATE wystarczy użyć nowego sposobu z @cminatti


Stara odpowiedź do celów historycznych

IMO lepiej jest użyć select () i on (), ponieważ w ten sposób można mieć wiele procedur obsługi zdarzeń zmiany rozmiaru... just don ' t get too crazy

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
Author: slf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-15 16:45:36

To trochę brzydkie, jeśli kod zmiany rozmiaru jest prawie tak długi, jak kod do budowania wykresu na pierwszym miejscu. Zamiast zmieniać rozmiar każdego elementu istniejącego wykresu, dlaczego nie po prostu go przeładować? Oto jak to u mnie działało:

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...
}

Linia kluczowa to d3.select('svg').remove();. W przeciwnym razie każda zmiana rozmiaru spowoduje dodanie kolejnego elementu SVG poniżej poprzedniego.

 12
Author: Raik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-03 02:46:21

W obowiązujących układach samo ustawienie atrybutów "wysokość" i "szerokość" nie będzie działać, aby ponownie wyśrodkować / przenieść wykres do kontenera svg. Istnieje jednak bardzo prosta odpowiedź, która działa dla układów siłowych znalezionych TUTAJ . W skrócie:

Użyj tego samego (dowolnego) WKKW, które lubisz.

window.on('resize', resize);

Wtedy zakładając, że masz zmienne 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();
}

W ten sposób, nie renderujemy grafu całkowicie, ustawiamy atrybuty i D3 ponownie oblicza rzeczy, jeśli jest to konieczne. To w najmniej działa, gdy używasz punktu ciężkości. Nie jestem pewien, czy jest to warunek wstępny dla tego rozwiązania. Czy ktoś może potwierdzić lub zaprzeczyć ?

Zdrówko, G
 8
Author: gavs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-12 21:31:41

Używam window.innerWidth dla szerokości i okna klienta.innerHeight dla wzrostu klienta.

 0
Author: Akshay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-24 17:38:14