在D3多线图表中将圆圈附加到1行

时间:2014-01-22 15:55:53

标签: d3.js

我有一个多线图表,代表给定日期的8个不同系列的值: http://bl.ocks.org/eoiny/8548406

我已设法过滤掉 series1 并仅为 series1 的每个数据点附加圈子,使用:

var filtered = city
      .filter(function(d){
          return d.name == "series1"
      })

      filtered           
            .selectAll('circle')
            .data(
              function(d){return d.values}                
                  )
            .enter().append('circle')
            .attr({
              cx: function(d,i){
                return x(d.date)
              },
              cy: function(d,i){
                return y(d.pindex)
              },
              r:  5
            })

但是我试图将4个圆圈附加到我的series1行,仅为以下每个值添加一个:

  1. 系列1中的最小值,
  2. series1中的最大值,
  3. series1中的第一个值,
  4. series1中的最后一个值。
  5. 我通过查看“过滤”数组来解决这个问题,我尝试使用类似这样的东西来捕捉最小值和最小值。最大值以:

    开头
    .attr("visibility", function(d) {
         if (d.pindex == d3.max(filtered, function(d) { return d.pindex; })) {return "visible"}
         if (d.pindex == d3.min(filtered, function(d) { return d.pindex; })) {return "visible"}
         else    { return "hidden" }  
                     ;}) 
    

    但是由于我需要的数据是在过滤后的数组中的一个对象中,我在某种程度上变得混乱。我知道过滤后应该是这样的:

    [{
    name: "series1",
      values: [{date: "2005-01-01",
                   pindex: "100"},
                  {date: "2005-02-01"
                  pindex: "100.4"}, ...etc for all data points i.e. dates
                 ]
        }] 
    

    所以我尝试过这样的事情:

    d.pindex == d3.max(filtered, function(d) { return d.values.pindex; })
    

    但我仍然有点失落。有没有人有任何想法?

1 个答案:

答案 0 :(得分:0)

通常,您可能希望过滤数据而不是DOM元素。因此,您可以使用city.filter来获取您感兴趣的数据数组,而不是使用cities.filter。更重要的是,您可能希望过滤传递给新circle选择的数据,而不是而不是创建所有圆圈,然后有选择地显示或隐藏它们。我可能会尝试:

filtered           
    .selectAll('circle')
    .data(function(d){
        var points = d.values;
        // create the array of desired points, starting with the easy ones
        var circleData = [
            // first
            points[0],
            // last
            points[points.length - 1]
        ];
        // now find min and max
        function getValue(d) { return d.pindex; }
        // d3.max returns the max value, *not* the object that contains it
        var maxVal = d3.max(points, getValue);
        // Note that you might have multiple points with the max. If you
        // don't want them all, just take maxPoints[0]
        var maxPoints = points.filter(function(d) { return d.pindex === maxVal; });
        // same for min
        var minVal = d3.min(points, getValue);
        var minPoints = points.filter(function(d) { return d.pindex === minVal; });
        // stick them all together
        return circleData.concat(maxPoints).concat(minPoints);
    })
    .enter().append('circle')
    // etc

关键点:

  • 过滤您的数据,而不是您的DOM。它的处理成本更低,更容易调试,而且通常更容易理解。

  • d3.mind3.max不返回具有最大值的对象,它们会返回值本身,因此您的TypeError