[英]D3 x-Axis not showing correctly
I'm trying to create a bar chart with data achieved from JSON. 我正在尝试使用从JSON实现的数据创建条形图。 This was working properly in my test drive, that had data from csv, but I'm having problem showing the x-axis in my graph.
这在我的测试驱动器中正常工作,其中包含来自csv的数据,但是在显示图形中的x轴时遇到问题。 Here is how it's currently displayed:
当前显示方式如下:
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleOrdinal().range([0, width]);
var y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json(urljson, function(error, data) {
data = data.results;
data.forEach(function(d) {
d.result = +d.result;
});
console.log(data);
x.domain(data.map(function(d) {return d.date } ));
y.domain([0, d3.max(data, function(d) {return d.result; })]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + (height) + ")")
.call(d3.axisBottom(x));
console.log(x.domain());
console.log(y.domain());
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Value");
g.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(d) {return x(d.date); })
.attr("y", function(d) {return y(d.result); })
.attr("height", function(d) {return height - y(d.result);})
});
and the JSON I am using looks like this: 我正在使用的JSON如下所示:
{
"count": 5,
"next": null,
"previous": null,
"results": [
{
"date": "2017-09-22",
"result": 35.9
},
{
"date": "2017-09-23",
"result": 65.12
},
{
"date": "2017-09-24",
"result": 11.23
},
{
"date": "2017-09-25",
"result": 77.8
},
{
"date": "2017-09-26",
"result": 108.98
}
]
}
Since x
is an ordinal scale, you have to set a range with the same number of elements of the domain. 由于
x
是序数标度,因此必须设置一个具有相同域元素数量的范围。 According to the API: 根据API:
If there are fewer elements in the range than in the domain, the scale will reuse values from the start of the range.
如果范围中的元素少于域中的元素,则比例尺将从范围开始重新使用值 。 (emphasis mine)
(强调我的)
This is a demo, that shows the behaviour of your code: all the values in the domain will be printed at 0
or width
: 这是一个演示,演示了代码的行为:域中的所有值都将以
0
或width
打印:
var svg = d3.select("svg"); var scale = d3.scaleOrdinal() .domain(["foo", "bar", "baz", "foobar", "foobaz"]) .range([10, 290]) var xAxis = d3.axisBottom(scale); svg.append("g") .attr("transform", "translate(0,50)") .call(xAxis);
<script src="https://d3js.org/d3.v4.min.js"></script> <svg></svg>
Solution : An easy alternative is using a band scale (or a point scale, depending on your goals). 解决方案 :一种简单的替代方法是使用带刻度(或点刻度,具体取决于您的目标)。 So, it should be:
因此,应为:
var x = d3.scaleBand().range([0, width]);
This is the same code using a band scale: 这是使用带刻度的相同代码:
var svg = d3.select("svg"); var scale = d3.scaleBand() .domain(["foo", "bar", "baz", "foobar", "foobaz"]) .range([10, 290]) var xAxis = d3.axisBottom(scale); svg.append("g") .attr("transform", "translate(0,50)") .call(xAxis);
<script src="https://d3js.org/d3.v4.min.js"></script> <svg></svg>
PS: I see that in your code your rectangles have no width. PS:我看到在您的代码中,矩形没有宽度。 If you decide to use the band scale, you can do:
如果决定使用带刻度,则可以执行以下操作:
.attr("width", x.bandwidth())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.