如何在d3线图中的特定点之间对线段进行着色?

时间:2014-06-26 23:50:49

标签: d3.js colors

我有一个简单的时间线图,它是动态更新的A数据值。也就是说,我定期添加一个新的数据值,一旦达到“最大值”,我就会在添加新值时从数据集中删除数据值。线图是“动画的”,这是有效的,以便在线的右端出现一个新点,而最旧的点从左边消失。根据新数据的某些属性(绘制的值和其他一些相关值),我需要改变连接最新数据值和一定数量的先前绘制数据值的线段的外观。

例如,假设数据值是由{Time,DataValueToPlot,FlagValue}组成的简单“对象”。正如我所说,我目前正在针对时间的X轴绘制每个数据对象的“DataValueToPlot”。假设绘制的最后3个值是(1 PM,10),(2 PM,20)和(3 PM,30)(尽管实际时间不均匀)。我们已经绘制了10,20和30,现在新的值(4 PM,15)到达并且15值被添加到线图中,但是这个新值有一个相关的FlagValue,表示前面的三个线段是比方说,用红色绘制,笔画宽度大。如何实现这一目标?

要明确的是,当任何数据值超出或低于指定值时,我不是要求绘制彩色线段,而是我需要能够更改所选线段的外观。

=======================对@jshanley的回应 感谢您的示例代码。我看到它允许我将适当的颜色与“线”(段)相关联,但我无法使其工作。我最初使用了将数据数组绑定到svg路径的常见模式,其中我使用了一个行函数来描述如何绘制数据点,如:

lineFcn = d3.svg.line()
        .x(function(d) { return(d.Time); })
        .y(function(d) { return(d.DataValueToPlot); })
        .interpolate("linear");
var svgContainer = d3.select("body").append("svg")
                                    .attr("width",500)
                                    .attr("height",500);
var lineGraph = svgContainer.append("path")
                            .attr("d", lineFcn(lineData))
                            .attr("stroke","black")
                            .attr("stroke-width",1)
                            .attr("fill","none");

这种方法的问题在于我无法将建议应用于它,因为您将笔划属性与每个“线”(线段)相关联,但在上面的代码中我们没有任何这样的元素。我试图重写代码,以便我不使用带有svg line()辅助函数的svg路径,而只是创建一个单独的“线段”的集合。这意味着在你的“输入”代码块中,我们扩展了selection.enter()。append('line')来添加X1,Y1和X2,Y2坐标,但这就是问题所在。我无法找到任何允许我定义这些值的方法。

我试图将你的建议扩展到:

selection.enter().append('line')
        .attr("x1",function(d,i) { return(d[i-1].Time); })
        .attr("y1",function(d,i) { return(d[i-1].DataValueToPlot)); })
        .attr("x2",function(d,i) { return(d].Time); })
        .attr("y2",function(d,i) { return(d].DataValueToPlot)); })

但是对“d [i-1]”的引用会触发错误。

1)访问器功能是否有某种方式可以引用“先前”数据值? 2)您是否可以扩展先前的代码示例以向我展示如何实际绘制设置笔触属性的每个线段?

谢谢!

1 个答案:

答案 0 :(得分:1)

假设您正在使用标准的Enter,Update,Exit模式described here,您可以在更新部分插入一些分支逻辑,并根据FlagValue是否出现来切换颜色或其他样式。

function update(data) {

  // reset the flag
  var flagged = false;

  var selection = svg.selectAll('line')
    .data(data);

  // ENTER
  selection.enter().append('line')
    // adding the attribute is superfluous
    //  but it gives us a callback in which
    //  we can set `flagged` to `true`
    .attr('data-flagged', function(d) {
       if (d.FlagValue === true) {
         flagged = true;
         return true;
       } else {
         return false;
       }
    });

  // ENTER + UPDATE
  // set the stroke based on whether `flagged` is true
  selection.attr('stroke', function(d) {
    if (flagged) {
      // could also add more conditional
      //  logic here to change only certain lines
      //  for example
      // if (d.time < someTimeVar) { return 'blue'; }
      return 'red';
    } else {
      return 'green';
    }
  });

  // EXIT
  selection.exit().remove();

}