d3.js - texto - Actualizar el eje y de un gráfico de área cepillada
tspan (2)
Estoy usando d3.js, y estoy trabajando en un gráfico de área cepillada modificando este ejemplo . Además del cambio del eje x basado en el pincel, me gustaría que el eje y del gráfico se vuelva a dibujar, basado en los valores y de los datos que caen dentro del pincel (similar al comportamiento de un gráfico de Google Finance ) .
He conseguido que la funcionalidad funcione, pero solo de una manera que permite dibujar el pincel tanto en el espacio x como en el espacio y. Hice esto agregando primero una escala a la variable de brush
:
var brush = d3.svg.brush()
.x(x2)
.y(y2)
.on("brush", brush);
Esto hace que brush.extent()
devuelva la siguiente matriz multidimensional: [ [x0, y0], [x1, y1] ]
. Luego uso estos datos en la función brush()
para redefinir los dominios x e y para el gráfico de enfoque:
function brush() {
var extent = brush.extent();
x.domain(brush.empty() ? x2.domain() : [ extent[0][0], extent[1][0] ]);
y.domain(brush.empty() ? y2.domain() : [ extent[0][1], extent[1][1] ]);
focus.select("path").attr("d", area);
focus.select(".x.axis").call(xAxis);
focus.select(".y.axis").call(yAxis);
}
Esto funciona, pero al definir la escala y en la variable de pincel, el usuario ahora puede arrastrar ''cuadros'' en el cuadro de enfoque, en lugar de solo poder arrastrar de oeste a este, como en el cuadro original.
Esencialmente, mi pregunta es: ¿cómo obtengo el rango de valores que se encuentran dentro del área de un pincel, en lugar del rango del área del pincel? ¿Es esto posible?
La documentación del pincel de d3 está here .
Se me ocurrió una solución.
Utilicé el dominio x.filtrado por el pincel para filtrar hacia abajo mi conjunto de datos original. Este nuevo conjunto de datos filtrados tiene solo los valores que caen dentro del pincel:
// Use x.domain to filter the data, then find the max and min duration of this new set, then set y.domain to that
x.domain(brush.empty() ? x2.domain() : brush.extent());
var dataFiltered = data.filter(function(d, i) {
if ( (d.date >= x.domain()[0]) && (d.date <= x.domain()[1]) ) {
return d.duration;
}
})
y.domain([0, d3.max(dataFiltered.map(function(d) { return d.duration; }))]);
Por último, asegúrese de volver a dibujar el eje y, así como el eje x:
focus.select("path").attr("d", area);
focus.select(".x.axis").call(xAxis);
focus.select(".y.axis").call(yAxis);
Una posibilidad más corta sería usar d3.scale.invert()
en tu brush.extent()
manera:
var domainExtent = brush.extent().map(function(d){return scale.invert(d);});
var filteredData = data.filter(function(d){return ((d <= domainExtent[1]) && (d >= domainExtent[0]));});
Sin embargo , por ahora d3 ha ganado d3.brushX()
, que solo permite el cepillado en dirección Este / Oeste por diseño.