Redimensionar svg quando a janela é redimensionada em d3.js

Estou desenhando um gráfico de dispersão com d3.js. Com a ajuda desta pergunta:
Obtém o tamanho da canvas, a página da web atual e a janela do navegador

Eu estou usando esta resposta:

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; 

Então eu sou capaz de encheckboxr minha trama na janela do usuário assim:

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

Agora eu gostaria que algo cuida de resize o enredo quando o usuário resize a janela.

PS: Eu não estou usando o jQuery no meu código.

Procure por ‘SVG responsivo’ é bastante simples fazer um SVG responsivo e você não precisa se preocupar mais com tamanhos.

Aqui está como eu fiz:

 d3.select("div#chartId") .append("div") .classd("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 .classd("svg-content-responsive", true); 

O código 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; } 

Mais informações / tutoriais:

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

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

Use window.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/

UPDATE é só usar o novo caminho do @cminatti


resposta antiga para fins históricos

IMO é melhor usar select () e on (), pois dessa forma você pode ter vários manipuladores de events de redimensionamento … apenas não fique muito louco

 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/

É meio feio se o código de redimensionamento é quase tão longo quanto o código para construir o gráfico em primeiro lugar. Então, em vez de resize todos os elementos do gráfico existente, por que não simplesmente recarregá-lo? Aqui está como isso funcionou para mim:

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

A linha crucial é d3.select('svg').remove(); . Caso contrário, cada redimensionamento adicionará outro elemento SVG abaixo do anterior.

Em layouts de força, simplesmente definir os atributos ‘height’ e ‘width’ não funcionará para recentrar / mover o gráfico para o contêiner svg. No entanto, há uma resposta muito simples que funciona para o Force Layouts encontrado aqui . Em suma:

Use o mesmo (qualquer) evento que você gosta.

 window.on('resize', resize); 

Então, supondo que você tenha 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(); } 

Desta forma, você não renderiza o gráfico inteiramente, nós definimos os atributos e o d3 re-calcula as coisas conforme necessário. Isso pelo menos funciona quando você usa um ponto de gravidade. Não tenho certeza se isso é um pré-requisito para essa solução. Alguém pode confirmar ou negar ?

Felicidades, g

Eu uso window.innerWidth para largura do cliente e window.innerHeight para a altura do cliente.