我正在使用d3.js创建事件的时间轴。一行中的某些事件相互重叠。即,下一个在前一个结束之前开始。 e.g:
对于每个栏,如果它与前一个栏重叠,我想将其移动:
我该怎么做? Here's a JSfiddle that generates the first example.
以下是一些相关部分:
var spanX = function(d, i) { return xScale(d['begin']); },
spanY = function(d) { return 0; },
spanW = function(d, i) {
return xScale(d['end']) - xScale(d['begin']);
},
spanH = 10;
var span = chart.selectAll('.chart-span')
.data(data)
.enter().append('rect')
.classed('chart-span', true)
.attr('x', spanX)
.attr('y', spanY)
.attr('width', spanW)
.attr('height', spanH);
(还有其他问题,例如在同一个图表上显示更多时间轴,并在左侧显示描述每个时间轴的标签......但一次只出现一个问题!)
更新:对于以下人士,请查看完成的图表:http://spelunker.moma.org/departments/(2017-02-08)
答案 0 :(得分:1)
最好的解决方案是创建一个算法来检查前一个柱的结束,并根据之前的柱结束设置下一个柱的y位置(这样的算法将是您下两个问题的基础, ...在同一图表上相互显示更多时间轴,并在左侧显示描述每个时间轴的标签“)。
但是,由于简单(和懒惰),如果您的数据不是动态的或您的图表不是非常复杂,您可以设置(硬编码)数据中的位置:
var data = [
{'begin': 2001, 'end': 2005, 'pos': 1},
{'begin': 2006, 'end': 2010, 'pos': 1},
{'begin': 2008, 'end': 2012, 'pos': 2},
{'begin': 2011, 'end': 2015, 'pos': 3}
];
然后定义您的y比例和spanY
:
yScale.domain(data.map(d=> d.pos))
.range([0, height]);
spanY = function(d) { return yScale(d.pos); }
这是一个演示:
var data = [
{'begin': 2001, 'end': 2005, 'pos': 1},
{'begin': 2006, 'end': 2010, 'pos': 1},
{'begin': 2008, 'end': 2012, 'pos': 2},
{'begin': 2011, 'end': 2015, 'pos': 3}
];
var margin = {top: 20, right: 30, bottom: 50, left: 40},
width = 500 - margin.left - margin.right,
height = 120 - margin.top - margin.bottom,
xScale = d3.scaleBand(),
yScale = d3.scaleBand(),
xAxis = d3.axisBottom(xScale),
minX = d3.min(data, function(d) { return d['begin']; }),
maxX = d3.max(data, function(d) { return d['end']; });
xScale.domain(d3.range(minX, maxX+1));
xScale.rangeRound([0, width]);
yScale.domain(data.map(d=> d.pos))
.range([0, height]);
var spanX = function(d, i) { return xScale(d['begin']); },
spanY = function(d) { return yScale(d.pos); },
spanW = function(d, i) {
return xScale(d['end']) - xScale(d['begin']);
},
spanH = 10;
var chart = d3.select('.chart')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.left + margin.right)
.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Add x axis
chart.append("g")
.attr("class", "axis axis-x");
chart.select('.axis-x')
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add spans
var span = chart.selectAll('.chart-span')
.data(data)
.enter().append('rect')
.classed('chart-span', true)
.attr('x', spanX)
.attr('y', spanY)
.attr('width', spanW)
.attr('height', spanH);
.chart-span {
fill: #333;
opacity: 0.5;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg class="chart"></svg>
PS:同样,这个硬编码解决方案对于您接下来的两个问题(“...在同一个图表上显示更多时间轴,并显示描述左侧“”上每个时间轴的标签。当您发布这些问题时,请更详细地描述数据的方式,以便人们可以考虑使用一种好的算法来计算条形位置。