由于您在交叉点处没有数据点,因此最简单的解决方案可能是获取每条线上方和下方的区域并使用clipPaths 来裁剪差异。
我假设您使用d3.svg.line 来绘制区域所基于的线条。这样我们以后就可以在这些区域上重复使用 .x() 和 .y() 访问器函数:
var trafficLine = d3.svg.line()
.x(function(d) { return x(d3.time.format("%m/%d/%Y").parse(d.original.date)); })
.y(function(d) { return y(parseInt(d.original.traffic)); });
var rateLine = d3.svg.line()
.x(trafficLine.x()) // reuse the traffic line's x
.y(function(d) { return y(parseInt(d.original.rate)); })
您可以创建单独的面积函数来计算两条线上方和下方的面积。每条线下方的区域将用于绘制实际路径,上方的区域将用作剪切路径。现在我们可以重用这些行中的访问器:
var areaAboveTrafficLine = d3.svg.area()
.x(trafficLine.x())
.y0(trafficLine.y())
.y1(0);
var areaBelowTrafficLine = d3.svg.area()
.x(trafficLine.x())
.y0(trafficLine.y())
.y1(height);
var areaAboveRateLine = d3.svg.area()
.x(rateLine.x())
.y0(rateLine.y())
.y1(0);
var areaBelowRateLine = d3.svg.area()
.x(rateLine.x())
.y0(rateLine.y())
.y1(height);
...height 是图表的高度,假设 0 是图表顶部的 y 坐标,否则相应地调整这些值。
现在您可以使用 area-above 函数来创建剪切路径,如下所示:
var defs = svg.append('defs');
defs.append('clipPath')
.attr('id', 'clip-traffic')
.append('path')
.datum(YOUR_DATASET)
.attr('d', areaAboveTrafficLine);
defs.append('clipPath')
.attr('id', 'clip-rate')
.append('path')
.datum(YOUR_DATASET)
.attr('d', areaAboveRateLine);
id 属性是必需的,因为我们在实际剪切路径时需要参考这些定义。
最后,使用 area-below 函数绘制到 svg 的路径。这里要记住的重要一点是,对于每个下方区域,我们需要剪切到对面上方区域,因此 Rate 区域将根据#clip-traffic 进行剪切,反之亦然:
// TRAFFIC IS ABOVE RATE
svg.append('path')
.datum(YOUR_DATASET)
.attr('d', areaBelowTrafficLine)
.attr('clip-path', 'url(#clip-rate)')
// RATE IS ABOVE TRAFFIC
svg.append('path')
.datum(YOUR_DATASET)
.attr('d', areaBelowRateLine)
.attr('clip-path', 'url(#clip-traffic)')
之后,您只需为这两个区域提供不同的填充颜色或您想要做的任何事情以将它们彼此区分开来。希望对您有所帮助!