Линия центрального пути D3 v5 на гистограмме

#d3.js

#d3.js

Вопрос:

Я использую d3.js v5 для построения гистограммы проблема заключается в том, что при создании гистограммы и добавлении пути вместе со столбцами пути не попадают в центр столбца, вместо того, чтобы он помещался в начальную точку, есть ли какой-либо способ центрировать точку, в настоящее время график выглядит следующим образом введите описание изображения здесь

Но я хочу, чтобы маленькие круги и точки были в центре извините за плохое изображение, я просто визуализирую свою концепцию, коричневые линии находятся в центре и будут соединены путем введите описание изображения здесь

 var margin = {
    top: 10,
    right: 30,
    bottom: 90,
    left: 40
  },
  width = 900 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;
this.x_axis = Array(20).fill(0).map((x, i) => (i   1) * 5);
this.y_axis = [1.1, 2.2, 3.5, 4.9, 5.3, 6.9, 7.3, 8.1, 9.2, 8.2, 1.3, 0.1, 0.1, 0.4, 0.1, 0.4, 0.2, 0.4, 0.1, 0.2];

let data = [];
for (let i = 0; i < this.x_axis.length; i  ) {
  data.push({
    Country: this.x_axis[i],
    Value: this.y_axis[i]
  })
}
var svg = d3.select("#graph")
  .append("svg")
  .attr("width", width   margin.left   margin.right)
  .attr("height", height   margin.top   margin.bottom)
  .append("g")
  .attr("transform",
    "translate("   margin.left   ","   margin.top   ")");

// Parse the Data

// X axis
var x = d3.scaleBand()
  .range([0, width])
  .domain(data.map(function(d) {
    return d.Country;
  }))
  .padding(0.3);
svg.append("g")
  .attr("transform", "translate(0,"   height   ")")
  .call(d3.axisBottom(x))
  .selectAll("text")
  .attr("transform", "translate(-10,0)rotate(-45)")
  .style("text-anchor", "end");

// Add Y axis
var y = d3.scaleLinear()
  .domain([0, 20])
  .range([height, 0]);
svg.append("g")
  .call(d3.axisLeft(y));

var x2 = d3.scaleBand()
  .range([0, width]);

// Bars
svg.selectAll("mybar")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", function(d) {
    return x(d.Country);
  })
  .attr("width", x.bandwidth())
  .attr("fill", "#69b3a2")
  // no bar at the beginning thus:
  .attr("height", function(d) {
    return height - y(0);
  }) // always equal to 0
  .attr("y", function(d) {
    return y(0);
  })

// Animation
svg.selectAll("rect")
  .transition()
  .duration(800)
  .attr("y", function(d) {
    return y(d.Value);
  })
  .attr("height", function(d) {
    return height - y(d.Value);
  })
  .delay(function(d, i) {
    console.log(i);
    return (i * 100)
  })

svg.append("path")
  .datum(data)
  .attr("fill", "none")
  .attr("stroke", "black")
  .attr("stroke-width", 1)
  .attr("d", d3.line()
    .x(function(d) {
      return x(d.Country)
    })
    .y(function(d) {
      return y(d.Value)
    }))

svg.selectAll("myCircles")
  .data(data)
  .enter()
  .append("circle")
  .attr("fill", "red")
  .attr("stroke", "none")
  .attr("cx", function(d) {
    return x(d.Country)
  })
  .attr("cy", function(d) {
    return y(d.Value)
  })
  .attr("r", 3)  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="graph"></div>  

Комментарии:

1. @altocumulus вы правы, я пропустил это. В будущем будет уделяться больше внимания

Ответ №1:

Поскольку вы используете scaleBand , ось автоматически возвращает не центр, а верхний левый угол прямоугольника, смещая его примерно x.bandwidth() / 2 . Одним из способов решения этой проблемы было бы использовать return x(d.Country) x.bandwidth() / 2 для нахождения центра столбцов.

 var margin = {
    top: 10,
    right: 30,
    bottom: 90,
    left: 40
  },
  width = 900 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;
this.x_axis = Array(20).fill(0).map((x, i) => (i   1) * 5);
this.y_axis = [1.1, 2.2, 3.5, 4.9, 5.3, 6.9, 7.3, 8.1, 9.2, 8.2, 1.3, 0.1, 0.1, 0.4, 0.1, 0.4, 0.2, 0.4, 0.1, 0.2];

let data = [];
for (let i = 0; i < this.x_axis.length; i  ) {
  data.push({
    Country: this.x_axis[i],
    Value: this.y_axis[i]
  })
}
var svg = d3.select("#graph")
  .append("svg")
  .attr("width", width   margin.left   margin.right)
  .attr("height", height   margin.top   margin.bottom)
  .append("g")
  .attr("transform",
    "translate("   margin.left   ","   margin.top   ")");

// Parse the Data

// X axis
var x = d3.scaleBand()
  .range([0, width])
  .domain(data.map(function(d) {
    return d.Country;
  }))
  .padding(0.3);
svg.append("g")
  .attr("transform", "translate(0,"   height   ")")
  .call(d3.axisBottom(x))
  .selectAll("text")
  .attr("transform", "translate(-10,0)rotate(-45)")
  .style("text-anchor", "end");

// Add Y axis
var y = d3.scaleLinear()
  .domain([0, 20])
  .range([height, 0]);
svg.append("g")
  .call(d3.axisLeft(y));

var x2 = d3.scaleBand()
  .range([0, width]);

// Bars
svg.selectAll("mybar")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", function(d) {
    return x(d.Country);
  })
  .attr("width", x.bandwidth())
  .attr("fill", "#69b3a2")
  // no bar at the beginning thus:
  .attr("height", function(d) {
    return height - y(0);
  }) // always equal to 0
  .attr("y", function(d) {
    return y(0);
  })

// Animation
svg.selectAll("rect")
  .transition()
  .duration(800)
  .attr("y", function(d) {
    return y(d.Value);
  })
  .attr("height", function(d) {
    return height - y(d.Value);
  })
  .delay(function(d, i) {
    console.log(i);
    return (i * 100)
  })

svg.append("path")
  .datum(data)
  .attr("fill", "none")
  .attr("stroke", "black")
  .attr("stroke-width", 1)
  .attr("d", d3.line()
    .x(function(d) {
      return x(d.Country)   x.bandwidth() / 2;
    })
    .y(function(d) {
      return y(d.Value)
    }))

svg.selectAll("myCircles")
  .data(data)
  .enter()
  .append("circle")
  .attr("fill", "red")
  .attr("stroke", "none")
  .attr("cx", function(d) {
    return x(d.Country)   x.bandwidth() / 2
  })
  .attr("cy", function(d) {
    return y(d.Value)
  })
  .attr("r", 3)  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="graph"></div>