(这是一个非常有趣的数据并列!)
IMO 序数尺度对此过于笨拙,但更重要的是,如果一条线路不止一次穿过同一个行政区(如M线,它在皇后区开始和结束),就会出现问题;因为序数比例需要唯一的值。
最好的解决方案可能是首先构建一个数据数组,表示每个行政区的起始位置和它跨越的站点数量。例如,对于M线,它看起来像这样:
[
{
"county": "81",
"countyName": "Queens"
"start": 1,
"span": 14
},
{
"county": "61",
"countyName": "Manhattan"
"start": 15,
"span": 10
},
{
"county": "47",
"countyName": "Brooklyn"
"start": 25,
"span": 7
},
{
"county": "81",
"countyName": "Queens"
"start": 32,
"span": 5
}
]
创建此数据数组的一种(有点神秘但非常简洁)方法是reduce()
在过滤后的数据上调用该方法。像这样:
boroughs = filtered_data.reduce(
function(memo, stop, i) {
var len = memo.length;
if(len == 0 || (memo[len - 1].county != stop.county)) {
memo.push({
county: stop.county,
start: i+1,
span: 1
countyName: "foo"// This needs a dictionary mapping county code to name
});
}
else {
memo[len - 1].span++;
}
return memo;
},
[]
)
构建此数据后,您将其绑定到 d3 选择并为每个条目创建一个组。即,如果一条线穿过 3 个行政区,您将创建 3 个组。在每个组内,您可以附加一个text
代表行政区名称和一个rect
或line
代表描述。像这样的东西:
// note the use of your `stop_scale` for calculating positions/widths
d3.selectAll('g.borough').data(boroughs)
gCounties.enter()
.append('g')// Create a group
.attr('class', 'borough'
.attr('transform', function(d) {// move the group to its appropriate x position
return 'translate(' + stop_scale(d.start+1) + ')';
})
.each(function(d, i) {// inside each group:
// append a rect (this is just an example)
d3.select(this)
.append('rect')
.style('stroke', '#000')
.attr('x', 0)
.attr('width', stop_scale(d.span))
.attr('height', 50);// This height should be changed to match your chart
// append a text
d3.select(this)
.append('text')
.text(d.countyName);
});
顺便说一句,您的代码可以使用重构。您不必在draw_first_line
andupdate_chart
函数之间重复代码。有关这方面的更多信息,请查看d3 教程页面上的通用更新模式(第 I、II 和 III 部分)。