javascript - examples - jquery d3
d3.js: barras espaciadas uniformemente en una escala de tiempo (3)
Prueba d3.scale.ordinal
var y = d3.scale.ordinal()
.domain(yourDomain)
.rangeRoundBands([0, chartHeight], 0.2);
Ajustar el parámetro 0.2 .
Estoy construyendo un diagrama de barras en d3.js en el que cada barra representa un total de casos de TB durante un mes. Los datos consisten esencialmente en una fecha (inicialmente cadenas en formato% Y-% m, pero analizadas utilizando d3.time.format.parse) y un entero. Me gustaría que las etiquetas de los ejes fueran relativamente flexibles (mostrar solo los límites del año, etiquetas cada mes, etc.), pero también me gustaría que las barras estuvieran espaciadas uniformemente.
Puedo usar el etiquetado de ejes flexible cuando uso una escala de fecha:
var xScaleDate = d3.time.scale()
.domain(d3.extent(thisstat, function(d) { return d.date; }))
.range([0, width - margin.left - margin.right]);
... pero las barras no están espaciadas uniformemente debido a la cantidad variable de días en cada mes (por ejemplo, febrero y marzo están notablemente más juntos que otros meses). Puedo obtener barras espaciadas uniformemente usando una escala lineal:
var xScaleLinear = d3.scale.linear()
.domain([0, thisstat.length])
.range([0, width - margin.left - margin.right]);
... pero no puedo averiguar cómo tener etiquetas de eje basadas en fecha. He intentado usar ambas escalas simultáneamente y solo generando un eje desde xScaleDate
, solo para ver qué sucedería, pero las escalas, naturalmente, no se alinean del todo bien.
¿Hay una manera sencilla de lograr esto que me estoy perdiendo?
Puedes combinar escalas ordinales y de tiempo:
// Use this to draw x axis
var xScaleDate = d3.time.scale()
.domain(d3.extent(thisstat, function(d) { return d.date; }))
.range([0, width - margin.left - margin.right]);
// Add an ordinal scale
var ordinalXScale = d3.scale.ordinal()
.domain(d3.map(thisstat, function(d) { return d.date; }))
.rangeBands([0, width], 0.4, 0);
// Now you can use both of them to space columns evenly:
columnGroup.enter()
.append("rect")
.attr("class", "column")
.attr("width", ordinalXScale.rangeBand())
.attr("height", function (d) {
return height - yScale(d.value);
})
.attr("x", function (d) {
return xScaleDate(d.date);
})
.attr("y", function (d){
return yScale(d.value);
});
He creado un ejemplo hace un tiempo para demostrar este enfoque: http://codepen.io/coquin/pen/BNpQoO
Tuve el mismo problema, terminé aceptando que algunos meses son más largos que otros y ajustando el ancho de la barra de la columna para que el espacio entre las barras permanezca constante. Así que ajustando la función barPath en la demostración de la página de inicio del filtro cruzado (http://square.github.com/crossfilter/ - usa d3) obtuve algo como esto:
var colWidth = Math.floor(x.range()[1] / groups.length) - 1;//9;
if (i < n - 1) {
//If there will be column on the right, end this column one pixel to the left
var nextX = x(groups[i+1].key)
colWidth = nextX - x(d.key) - 1;
}
path.push("M", x(d.key), ",", height, "V", yVal, "h",colWidth,"V", height);