¿Cómo usar x y ancho en un gráfico de barras con scaleTime?

Tengo un codepen aquí – https://codepen.io/anon/pen/xpaYYw?editors=0010

Es un gráfico de prueba simple, pero la fecha se formateará así.

Tengo fechas en el eje xy cantidades en el y

¿Cómo puedo usar la escala x para establecer el ancho y la posición x de las barras?

layers.selectAll('rect') .data(data) .enter() .append('rect') .attr('height', function(d, i) { return height - y(d.one); }) .attr('y', function(d, i) { return y(d.one); }) .attr('width', function(d, i) { return 50; }) .attr('x', function(d, i) { return 80*i; }) .style('fill', (d, i) => { return colors[i]; }); 

El problema con su pregunta no tiene nada que ver con progtwigción, JavaScript o D3 … el problema es un concepto básico de datos (por eso agregué la etiqueta de visualización de datos en su pregunta):

¡Lo que estás tratando de hacer no es correcto! No deberías usar barras con una escala de tiempo. Las escalas de tiempo son para series temporales (en las que usamos puntos o puntos conectados por líneas).

Si usa barras con tiempo en el eje x, tendrá problemas:

  1. Posicionando la barra: el margen izquierdo de la barra siempre estará en la fecha que establezca. Toda la barra estará después de esa fecha;
  2. Establecer el ancho de la barra: en un gráfico de barras real, que usa variables categóricas para el eje x, el ancho no tiene significado. Pero en una escala de tiempo, el ancho representa el tiempo .

Sin embargo, solo por el bien de la explicación, vamos a crear este gráfico de barras con una escala de tiempo (a pesar de que esta es una opción incorrecta ) … Aquí está cómo hacerlo:

Primero, configure el “ancho” de las barras a tiempo . Digamos, cada barra tendrá 10 días de ancho:

 .attr("width", function(d){ return x(d3.timeDay.offset(d.date, 10)) - x(d.date) }) 

Luego, establezca la posición x de la barra a la fecha actual menos la mitad de su ancho (es decir, menos de 5 días en nuestro ejemplo):

 .attr('x', function(d, i) { return x(d3.timeDay.offset(d.date, -5)); }) 

Finalmente, no te olvides de crear un “relleno” en la escala de tiempo:

 var x = d3.scaleTime() .domain([d3.min(data, function(d) { return d3.timeDay.offset(d.date, -10); }), d3.max(data, function(d) { return d3.timeDay.offset(d.date, 10); })]) .range([0, width]); 

Aquí está su código con esos cambios:

 var keys = []; var legendKeys = []; var maxVal = []; var w = 800; var h = 450; var margin = { top: 30, bottom: 40, left: 50, right: 20, }; var width = w - margin.left - margin.right; var height = h - margin.top - margin.bottom; var colors = ['#FF9A00', '#FFEBB6', '#FFC400', '#B4EDA0', '#FF4436']; var data = [{ "one": 4306, "two": 2465, "three": 2299, "four": 988, "five": 554, "six": 1841, "date": "2015-05-31T00:00:00" }, { "one": 4378, "two": 2457, "three": 2348, "four": 1021, "five": 498, "six": 1921, "date": "2015-06-30T00:00:00" }, { "one": 3404, "two": 2348, "three": 1655, "four": 809, "five": 473, "six": 1056, "date": "2015-07-31T00:00:00" }, ]; data.forEach(function(d) { d.date = new Date(d.date) }) for (var i = 0; i < data.length; i++) { for (var key in data[i]) { if (!data.hasOwnProperty(key) && key !== "date") maxVal.push(data[i][key]); } } var x = d3.scaleTime() .domain([d3.min(data, function(d) { return d3.timeDay.offset(d.date, -10); }), d3.max(data, function(d) { return d3.timeDay.offset(d.date, 10); })]) .range([0, width]); var y = d3.scaleLinear() .domain([0, d3.max(maxVal, function(d) { return d; })]) .range([height, 0]); var svg = d3.select('body').append('svg') .attr('class', 'chart') .attr('width', w) .attr('height', h); var chart = svg.append('g') .classed('graph', true) .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); var layersArea = chart.append('g') .attr('class', 'layers'); var layers = layersArea.append('g') .attr('class', 'layer'); layers.selectAll('rect') .data(data) .enter() .append('rect') .attr('height', function(d, i) { return height - y(d.one); }) .attr('y', function(d, i) { return y(d.one); }) // .attr('width', function(d, i) { // return 50; // }) .attr("width", function(d) { return x(d3.timeDay.offset(d.date, 10)) - x(d.date) }) .attr('x', function(d, i) { return x(d3.timeDay.offset(d.date, -5)); }) .style('fill', (d, i) => { return colors[i]; }); chart.append('g') .classed('x axis', true) .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x) .tickFormat(d3.timeFormat("%Y-%m-%d")).tickValues(data.map(function(d) { return new Date(d.date) }))); chart.append('g') .classed('y axis', true) .call(d3.axisLeft(y) .ticks(10));