【问题标题】:Using d3 to shade area between two lines使用 d3 对两条线之间的区域进行着色
【发布时间】:2014-09-17 22:21:35
【问题描述】:

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

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():

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

现在这主要是有效的,除非线交叉。如何在 BETWEEN 点之间的一条线下遮蔽区域?它基于点着色,我希望它基于线条着色。如果在线的一侧没有两个连续的点,我根本不会得到任何阴影。

【问题讨论】:

    标签: javascript d3.js linechart


    【解决方案1】:

    由于您在交叉点处没有数据点,因此最简单的解决方案可能是获取每条线上方和下方的区域并使用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)')
    

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    • 2017-07-13
    • 1970-01-01
    相关资源
    最近更新 更多