使用 d3 来遮蔽两条线之间的区域 [英] Using d3 to shade area between two lines

查看:19
本文介绍了使用 d3 来遮蔽两条线之间的区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一张图表,绘制了流量与日期和费率与日期的关系.我试图遮蔽两条线之间的区域.但是,我想根据哪条线更高,将其着色为不同的颜色.在没有最后一个要求的情况下,以下工作:

So I have a chart plotting traffic vs. date and rate vs. date. I'm trying to shade the area between the two lines. However, I want to shade it a different color depending on which line is higher. The following works without that last requirement:

var area = d3.svg.area()
    .x0(function(d) { return x(d3.time.format("%m/%d/%Y").parse(d.original.date)); })
    .x1(function(d) { return x(d3.time.format("%m/%d/%Y").parse(d.original.date)); })
    .y0(function(d) { return y(parseInt(d.original.traffic)); })
    .y1(function(d) { return y(parseInt(d.original.rate)); })

然而,添加最后一个要求,我尝试使用defined():

However, adding that last requirement, I tried to use defined():

.defined(function(d){ return parseInt(d.original.traffic) >= parseInt(d.original.rate); })

现在这基本上有效,除非线交叉时.如何在点之间的一条线下对区域进行着色?它基于点着色,我希望它基于线着色.如果线的一侧没有连续的两个点,则根本看不到任何阴影.

Now this mostly works, except when lines cross. How do I shade the area under one line BETWEEN points? It's shading based on the points and I want it to shade based on the line. If I don't have two consecutive points on one side of the line, I don't get any shading at all.

推荐答案

由于在交叉点处没有数据点,最简单的解决方案可能是获取每条线上方和下方的区域并使用 clipPaths 来裁剪差异.

Since you don't have datapoints at the intersections, the simplest solution is probably to get the areas above and below each line and use clipPaths to crop the difference.

我假设您使用 d3.svg.line 来绘制区域所基于的线条.这样我们就可以稍后在区域上重用 .x().y() 访问器函数:

I'll assume you're using d3.svg.line to draw the lines that the areas are based on. This way we'll be able to re-use the .x() and .y() accessor functions on the areas later:

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)); })

您可以创建单独的面积函数来计算两条线上方和下方的面积.每条线下方的区域将用于绘制实际路径,上方的区域将用作剪切路径.现在我们可以重新使用行中的访问器:

You can create separate area functions for calculating the areas both above and below your two lines. The area below each line will be used for drawing the actual path, and the area above will be used as a clipping path. Now we can re-use the accessors from the lines:

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 坐标,否则相应地调整这些值.

...where height is the height of your chart, and assuming 0 is the y-coordinate of the top of the chart, otherwise adjust those values accordingly.

现在您可以使用 area-above 函数来创建这样的剪切路径:

Now you can use the area-above functions to create clipping paths like this:

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 属性是必需的,因为我们需要在实际剪切路径时引用这些定义.

The id attributes are necessary because we need to refer to those definitions when actually clipping the paths.

最后,使用 area-below 函数绘制到 svg 的路径.这里要记住的重要一点是,对于下面的每个区域,我们需要裁剪到对面区域-上面,因此将根据 #clip-traffic反之亦然:

Finally, use the area-below functions to draw paths to the svg. The important thing to remember here is that for each area-below, we need to clip to the opposite area-above, so the Rate area will be clipped based on #clip-traffic and vice versa:

// 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)')

之后,您只需为这两个区域设置不同的填充颜色或任何您想做的事情以将它们彼此区分开.希望有帮助!

After that you'll just need to give the two regions different fill colors or whatever you want to do to distinguish them from one another. Hope that helps!

这篇关于使用 d3 来遮蔽两条线之间的区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆