Tom*_*lum 2 javascript json linechart d3.js
我对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"
}
Run Code Online (Sandbox Code Playgroud)
我现在尝试使用折线图上的两条线将PassengersIn&PassengersOut映射到Destination.我正在与轴挣扎,因为x只有2个刻度,而y没有缩放到我的数据.如下所示;
我的代码如下.我删除了无关的Google Maps和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);
});
Run Code Online (Sandbox Code Playgroud)
我设法找到一些使用分类序数量表的例子,但是,它们都使用了d3.js的v3,并且在无数次阅读v4 API之后我仍然无法弄明白.
你想要一个分类尺度,这是正确的,但你不需要这里的顺序尺度.
从v3到v4有很多变化.在v3中,您可以将.rangeBands,.rangeRoundBands,.rangePoints和.rangeRoundPoints设置为您的序数比例,因此可以接受连续范围.不再是:在D3 v4中你拥有全新的scaleBand
和scalePoint
.
在第4节中,按常规顺序(即scaleOrdinal
):
如果指定了范围,则将序数范围的范围设置为指定的值数组.域中的第一个元素将映射到范围中的第一个元素,第二个域值将映射到第二个范围值,依此类推.如果范围中的元素少于域中的元素,则比例将重用范围开头的值.(强调我的)
因此,在a中scaleOrdinal
,范围需要具有相同的域长度(元素数量).
话虽这么说,你想要一个点刻度(scalePoint
).带秤和点刻度......
...除了输出范围是连续的和数字之外,都像序数标度.(强调我的)
检查此代码段,查看控制台并比较两个比例:
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))
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://d3js.org/d3.v4.min.js"></script>
Run Code Online (Sandbox Code Playgroud)
关于你的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;
})]);
Run Code Online (Sandbox Code Playgroud)
改变顺序:
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);
Run Code Online (Sandbox Code Playgroud)