Supongamos que tengo un script de histograma que crea un gráfico de 960 500 svg. ¿Cómo hago que esto responda para cambiar el tamaño de los anchos gráficos y las alturas dinámicas?
<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>
El ejemplo completo de histograma es: https://gist.github.com/993912
javascript
responsive-design
d3.js
Matt Alcock
fuente
fuente
Respuestas:
Hay otra forma de hacer esto que no requiere volver a dibujar el gráfico, e implica modificar los atributos viewBox y preserveAspectRatio en el
<svg>
elemento:Actualización 24/11/15 : la mayoría de los navegadores modernos pueden inferir la relación de aspecto de los elementos SVG a partir de
viewBox
, por lo que es posible que no necesite mantener actualizado el tamaño del gráfico. Si necesita admitir navegadores antiguos, puede cambiar el tamaño de su elemento cuando la ventana cambie de tamaño de la siguiente manera:Y el contenido de svg se escalará automáticamente. Puede ver un ejemplo funcional de esto (con algunas modificaciones) aquí : simplemente cambie el tamaño de la ventana o el panel inferior derecho para ver cómo reacciona.
fuente
onload
llamada a la función. Si el ancho y la altura del svg se establecen en el html real y utiliza la técnica anterior, la imagen no será escalable.Busque 'SVG receptivo', es bastante simple hacer que un SVG responda y ya no tiene que preocuparse por los tamaños.
Así es como lo hice:
El código CSS:
Más información / tutoriales:
http://demosthenes.info/blog/744/Make-SVG-Responsive
http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php
fuente
He codificado una pequeña idea para resolver esto.
El patrón de solución general es este:
También agregué el script d3.js minimizado para la velocidad. La esencia está aquí: https://gist.github.com/2414111
código de referencia de jquery:
Código de rebote:
¡Disfrutar!
fuente
Sin usar ViewBox
Aquí hay un ejemplo de una solución que no depende del uso de
viewBox
:La clave está en actualizar el rango de las escalas que se utilizan para colocar datos.
Primero, calcule su relación de aspecto original:
Luego, en cada cambio de tamaño, actualice el
range
dex
yy
:Tenga en cuenta que la altura se basa en el ancho y la relación de aspecto, por lo que se mantienen sus proporciones originales.
Finalmente, "vuelva a dibujar" el gráfico: actualice cualquier atributo que dependa de cualquiera de las escalas
x
oy
:Tenga en cuenta que al cambiar el tamaño
rects
puede usar el límite superior derange
ofy
, en lugar de usar explícitamente la altura:Mostrar fragmento de código
fuente
Si está utilizando d3.js a través de c3.js, la solución al problema de la capacidad de respuesta es bastante sencilla:
donde se ve el HTML generado:
fuente
La respuesta de Shawn Allen fue genial. Pero es posible que no desee hacer esto cada vez. Si lo aloja en vida.io , obtiene respuesta automática para su visualización de svg.
Puede obtener un iframe receptivo con este código de inserción simple:
http://jsfiddle.net/dnprock/npxp3v9d/1/
Divulgación: construyo esta función en vida.io .
fuente
En el caso de que esté utilizando un contenedor d3 como plottable.js , tenga en cuenta que la solución más fácil podría ser agregar un detector de eventos y luego llamar a una función de redibujo (
redraw
en plottable.js). En el caso de plottable.js, esto funcionará excelentemente (este enfoque está mal documentado):fuente
En caso de que la gente siga visitando esta pregunta, esto es lo que funcionó para mí:
Encierre el iframe en un div y use css para agregar un relleno de, por ejemplo, 40% a ese div (el porcentaje depende de la relación de aspecto que desee). Luego, establezca el ancho y la altura del iframe en 100%.
En el documento html que contiene el gráfico que se cargará en el iframe, establezca el ancho al ancho del div al que se adjunta el svg (o al ancho del cuerpo) y establezca la relación de aspecto alto a ancho *.
Escriba una función que recargue el contenido del iframe al cambiar el tamaño de la ventana, para adaptar el tamaño del gráfico cuando las personas rotan su teléfono.
Ejemplo aquí en mi sitio web: http://dirkmjk.nl/en/2016/05/embedding-d3js-charts-responsive-website
ACTUALIZACIÓN 30 dic 2016
El enfoque que describí anteriormente tiene algunos inconvenientes, especialmente que no tiene en cuenta la altura de ningún título y subtítulos que no sean parte del svg creado por D3. Desde entonces me he encontrado con lo que creo que es un mejor enfoque:
Ejemplo aquí en mi sitio web: http://dirkmjk.nl/en/2016/12/embedding-d3js-charts-responsive-website-better-solution
fuente
Uno de los principios básicos de la unión de datos D3 es que es idempotente. En otras palabras, si evalúa repetidamente una unión de datos con los mismos datos, la salida representada es la misma. Por lo tanto, siempre que renderice su gráfico correctamente, tenga cuidado con sus selecciones de entrada, actualización y salida; todo lo que tiene que hacer cuando cambia el tamaño es volver a representar el gráfico en su totalidad.
Hay un par de otras cosas que debe hacer, una es retirar el controlador de cambio de tamaño de la ventana para acelerarlo. Además, en lugar de codificar anchos / alturas rígidas, esto debería lograrse midiendo el elemento contenedor.
Como alternativa, aquí está su gráfico representado con d3fc , que es un conjunto de componentes D3 que manejan correctamente las uniones de datos. También tiene un gráfico cartesiano que mide que contiene un elemento, lo que facilita la creación de gráficos 'receptivos':
Puedes verlo en acción en este codepen:
https://codepen.io/ColinEberhardt/pen/dOBvOy
donde puede cambiar el tamaño de la ventana y verificar que el gráfico se vuelva a representar correctamente.
Tenga en cuenta que, como divulgación completa, soy uno de los mantenedores de d3fc.
fuente
Evitaría cambiar el tamaño / marcar soluciones como la plaga, ya que son ineficientes y pueden causar problemas en su aplicación (por ejemplo, una información sobre herramientas vuelve a calcular la posición en la que debería aparecer en el cambio de tamaño de la ventana, luego, un momento después, su gráfico cambia de tamaño y la página vuelve a cambiar). diseños y ahora su información sobre herramientas está mal otra vez).
Puede simular este comportamiento en algunos navegadores más antiguos que no lo soportan correctamente como IE11 también usando un
<canvas>
elemento que mantiene su aspecto.Dado 960x540, que es un aspecto de 16: 9:
fuente
Muchas respuestas complejas aquí.
Básicamente, todo lo que necesita hacer es deshacerse de los atributos
width
yheight
en favor delviewBox
atributo:Si tiene márgenes, puede agregarlos allí en el ancho / alto y luego agregarlos a
g
continuación y transformarlos como lo haría normalmente.fuente
También puede usar bootstrap 3 para adaptar el tamaño de una visualización. Por ejemplo, podemos configurar el código HTML como:
He configurado una altura fija debido a mis necesidades, pero también puede dejar el tamaño automático. El "col-sm-6 col-md-4" hace que el div responda a diferentes dispositivos. Puede obtener más información en http://getbootstrap.com/css/#grid-example-basic
Podemos acceder al gráfico con la ayuda de la vista de id de mes .
No entraré en muchos detalles sobre el código d3, solo ingresaré la parte que se necesita para adaptarse a diferentes tamaños de pantalla.
El ancho se establece obteniendo el ancho del div con la vista id de mes.
La altura en mi caso no debe incluir toda el área. También tengo un texto sobre la barra, así que necesito calcular esa área también. Es por eso que identifiqué el área del texto con el id responsivetext. Para calcular la altura permitida de la barra, resta la altura del texto de la altura del div.
Esto le permite tener una barra que adoptará todos los diferentes tamaños de pantalla / div. Puede que no sea la mejor manera de hacerlo, pero seguramente funciona para las necesidades de mi proyecto.
fuente