我相对是 D3.js 的新手,我正在可视化我的 busdatasimple.json 文件中的“PassengersIn”和“PassengersOut”值。作为引用,其中一个 JSON 对象如下所示;
{
"BusNo": "1",
"Date": "21 November 2016",
"Time": "09:10:34 AM",
"Destination": "Pier 50",
"Longitude": "-122.383262",
"Latitude": "37.773644",
"PassengersIn": "8",
"PassengersOut": "1"
}
我现在尝试使用折线图上的两条线绘制 PassengersIn 和 PassengersOut 与 Destination 的关系图。我在轴上苦苦挣扎,因为 x 只有 2 个刻度,而 y 没有缩放到我的数据。如下所示;
我的代码如下。我删除了不相关的 Google map 和 jQuery。
//Setting The Dimensions Of The Canvas
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 650 - margin.left - margin.right,
height = 350 - margin.top - margin.bottom;
//Setting X & Y Ranges
var x = d3.scaleOrdinal().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
//Define The Axes
var xAxis = d3.axisBottom().scale(x);
var yAxis = d3.axisLeft().scale(y).ticks(10);
//Add The SVG Element
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right + 50)
.attr("height", height + margin.top + margin.bottom + 200)
.attr("class", "svg")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//Load Data From JSON
d3.json("busdatasimple.json", function(error, data) {
//Functions for Y-Axis Grid Lines
function yGridLines() {
return d3.axisLeft().scale(y).ticks(5);
}
//Adding the Y-Axis Grid Lines
svg.append("g")
.attr("class", "grid-lines")
.call(yGridLines().tickSize(-width, 0, 0).tickFormat(""));
//Adding Y-Axis
svg.append("g")
.attr("class", "y axis").call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 5)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Passengers In");
//Adding X-Axis (Added to the end of the code so the label show over bottom bars)
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "middle")
//.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "translate(-5, 15)")
.attr("font-family", "Arial")
.attr("font-weight", "bold")
.attr("font-size", "1.1em");
x.domain(data.map(function(d){return d.Destination;}));
y.domain([d3.min(data, function(d){return d.PassengersIn;}), d3.max(data, function(d) {return d.PassengersIn;})]);
var line = d3.line()
.x(function(d){return x(d.Destination);})
.y(function(d){return y(d.PassengersIn);});
svg.append("path").datum(data)
.attr("class", "line")
.attr("d", function(d){return d.PassengersIn;})
.attr("stroke", "green")
.attr("stroke-width", 2);
});
我设法找到了一些使用分类序数尺度的示例,但是,它们都使用了 d3.js 的 v3,并且在无数次阅读了 v4 API 之后,我仍然无法弄明白。
最佳答案
你想要一个分类尺度,这是正确的,但你不想要一个序数尺度。
从 v3 到 v4 有很多变化。在 v3 中,您可以将 .rangeBands、.rangeRoundBands、.rangePoints 和 .rangeRoundPoints 设置为您的序数比例,因此可以接受连续范围。不再是:在 D3 v4 中,您拥有全新的 scaleBand
和 scalePoint
。
在 v4 中,以常规序数比例(即 scaleOrdinal
):
If range is specified, sets the range of the ordinal scale to the specified array of values. The first element in the domain will be mapped to the first element in range, the second domain value to the second range value, and so on. If there are fewer elements in the range than in the domain, the scale will reuse values from the start of the range. (emphases mine)
因此,在 scaleOrdinal
中,范围需要与域的长度(元素数)相同。
话虽这么说,但您需要一个点比例尺 (scalePoint
)。带刻度和点刻度...
...are like ordinal scales except the output range is continuous and numeric. (emphasis mine)
检查此代码段,查看控制台并比较两个比例:
var destinations = ["foo", "bar", "baz", "foobar", "foobaz"];
var scale1 = d3.scaleOrdinal()
.range([0, 100])
.domain(destinations);
var scale2 = d3.scalePoint()
.range([0, 100])
.domain(destinations);
destinations.forEach(d=>{
console.log(d + " in an ordinal scale: " + scale1(d) + " / in a point scale: " + scale2(d))
})
<script src="https://d3js.org/d3.v4.min.js"></script>
关于您的 y 轴问题:
在调用轴之前设置 y 尺度的域。所以,而不是这个:
svg.append("g")
.attr("class", "y axis").call(yAxis);
y.domain([d3.min(data, function(d){
return d.PassengersIn;
}), d3.max(data, function(d){
return d.PassengersIn;
})]);
改变顺序:
y.domain([d3.min(data, function(d){
return d.PassengersIn;
}), d3.max(data, function(d){
return d.PassengersIn;
})]);//set the domain first!
svg.append("g")
.attr("class", "y axis").call(yAxis);
关于javascript - 在 D3.js (V4) 中创建分类折线图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41426884/