es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo colocar las barras de un gráfico de barras en las posiciones correctas del eje x utilizando d3.js?

Estoy haciendo un gráfico de barras, pero tengo problemas para coincidir las posiciones de las barras con el eje x. No están en el lugar correcto, por ejemplo, al pasar el cursor sobre la barra encima de la marca de 2010, se puede ver que muestra un valor de 2007. ¿Cómo puedo solucionar eso?

let url = "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json";

const padding = 50;
const height = 460;
const width = 940;
const barthickness = 2.909090909090909;

var svg = d3.select('body')
    .append('svg')
    .attr('width', width)
    .attr('height', height);

var arr = [];
var years = [];

d3.json(url, function(data) {
        for (let i = 0; i < data.data.length; i++) {
            arr[i] = data.data[i];
            years[i] = parseInt(data.data[i][0].slice(0,4));
        }  

     const yScale = d3.scaleLinear()
                      .domain([0, d3.max(arr, (d) => d[1])])
                      .range([height - padding, padding]);

    const xScale = d3.scaleLinear()
                       .domain([d3.min(years, d => d), d3.max(years, (d) => d)])
                       .range([padding, width - padding]);

const xAxis = d3.axisBottom(xScale);

const yAxis = d3.axisLeft(yScale);

    svg.append("g")
       .attr("transform", "translate(0," + (height - padding) + ")")
       .call(xAxis);

   svg.append('g')
      .attr('transform', 'translate(' + padding + ', 0)')
      .call(yAxis)

    svg.selectAll('rect')
        .data(arr)
        .enter()
        .append('rect')
        .attr('fill', 'blue')
        .attr('height', d => height - padding - yScale(d[1]))
        .attr('width', barthickness)
        .attr('x', (d, i) => padding + (3.2* i))
        .attr('y', d => yScale(d[1]))
        .append('title')
        .text((d, i) => years[i] + ': ' + d[1])
    });
        <script src="https://d3js.org/d3.v4.min.js"></script>
Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Parece que los valores del eje x no están alineados correctamente con las barras. Un posible problema podría ser que las coordenadas x de las barras no se estén calculando correctamente.

    En el fragmento de código, la coordenada x para cada barra se calcula utilizando la fórmula padding + (3.2 * i). Esta fórmula asume que cada barra tiene un ancho fijo de barthickness (que se establece en 2.909090909090909). Sin embargo, esto no es cierto ya que los datos de cada año pueden tener valores diferentes.

    Para solucionar este problema, puedes calcular la coordenada x para cada barra en función de su valor de año correspondiente. Primero, puedes modificar el array years para incluir solo años únicos (para evitar múltiples barras para el mismo año). Luego, puedes usar el método indexOf para obtener el índice del año actual en el array years, y usar ese índice para calcular la coordenada x de la barra.

    Aquí tienes un ejemplo de cómo puedes modificar el código para implementar este enfoque:

    d3.json(url, function(data) {
      var arr = data.data;
    
      // Extraer años únicos de los datos
      var years = [...new Set(arr.map(d => parseInt(d[0].slice(0,4))))];
    
      const yScale = d3.scaleLinear()
          .domain([0, d3.max(arr, (d) => d[1])])
          .range([height - padding, padding]);
    
      const xScale = d3.scaleLinear()
          .domain([d3.min(years), d3.max(years)])
          .range([padding, width - padding]);
    
      const xAxis = d3.axisBottom(xScale);
    
      const yAxis = d3.axisLeft(yScale);
    
      svg.append("g")
          .attr("transform", "translate(0," + (height - padding) + ")")
          .call(xAxis);
    
      svg.append('g')
          .attr('transform', 'translate(' + padding + ', 0)')
          .call(yAxis)
    
      svg.selectAll('rect')
          .data(arr)
          .enter()
          .append('rect')
          .attr('fill', 'blue')
          .attr('height', d => height - padding - yScale(d[1]))
          .attr('width', xScale(years[1]) - xScale(years[0])) // calcular ancho de la barra basado en la escala x
          .attr('x', d => xScale(parseInt(d[0].slice(0,4)))) // calcular coordenada x de la barra basado en la escala x y el valor del año
          .attr('y', d => yScale(d[1]))
          .append('title')
          .text((d, i) => years[i] + ': ' + d[1]);
    });
    

    En este código modificado, extraemos los años únicos de los datos utilizando los métodos map y Set, y usamos ese array para calcular las coordenadas x de las barras. Específicamente, utilizamos la escala xScale para calcular la coordenada x de cada valor de año, y usamos ese valor como coordenada x de la barra. También calculamos el ancho de cada barra en función de la escala x, para asegurarnos de que cada barra esté alineada con su correspondiente etiqueta del eje x.

Comments are closed.