Redimensionar svg cuando la ventana se redimensiona en d3.js
Estoy dibujando una gráfica de dispersión con d3.js. Con la ayuda de esta pregunta :
Obtenga el tamaño de la pantalla, la página web actual y la ventana del navegador
Estoy usando esta respuesta:
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;
Así que soy capaz de ajustar mi parcela a la ventana del usuario de esta manera:
var svg = d3.select("body").append("svg")
.attr("width", x)
.attr("height", y)
.append("g");
Ahora me gustaría que algo se encargue de cambiar el tamaño de la gráfica cuando el usuario cambie el tamaño de la ventana.
PD : No estoy usando jQuery en mi código.
6 answers
Busca 'responsive SVG' es bastante simple hacer un SVG responsive y ya no tienes que preocuparte por los tamaños.
Así es como lo hice:
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);
El 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;
}
Más información / tutoriales:
Http://thenewcode.com/744/Make-SVG-Responsive
Http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-28 10:53:41
Utilice la ventana .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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-15 23:46:59
ACTUALIZAR simplemente use la nueva forma de @cminatti
Antigua respuesta para propósitos históricos
IMO es mejor usar select() y on() ya que de esa manera puede tener múltiples controladores de eventos de redimensionamiento... simplemente no te vuelvas demasiado loco
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 /
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-15 16:45:36
Es un poco feo si el código de redimensionamiento es casi tan largo como el código para construir el gráfico en primer lugar. Entonces, en lugar de cambiar el tamaño de cada elemento del gráfico existente, ¿por qué no simplemente recargarlo? Así es como funcionó para mí:
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 línea crucial es d3.select('svg').remove();
. De lo contrario, cada redimensionamiento agregará otro elemento SVG debajo del anterior.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-03 02:46:21
En force layouts simplemente establecer los atributos 'height' y 'width' no funcionará para volver a centrar/mover la gráfica en el contenedor svg. Sin embargo, hay una respuesta muy simple que funciona para los diseños de fuerza que se encuentran aquí. En resumen:
Use el mismo (cualquier) evento que desee.
window.on('resize', resize);
Entonces asumiendo que tiene 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 esta manera, no se vuelve a renderizar el gráfico por completo, establecemos los atributos y d3 vuelve a calcular las cosas según sea necesario. Esto en menos funciona cuando se utiliza un punto de gravedad. No estoy seguro de si eso es un requisito previo para esta solución. ¿Alguien puede confirmar o negar ?
Salud, g
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-12 21:31:41
Uso ventana.innerWidth para el ancho y la ventana del cliente.Altura interior para la altura del cliente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-24 17:38:14