#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>