循环遍历多个对象中的对象数组并使用下划线访问 D3 中的值

Looping through array of objects within multiple objects and accessing values in D3 using underscore

D3d.js 中,我试图为数组中的每个对象附加矩形,所以高度矩形由值决定。此外,我正在努力做到只有每个数组中的第一个对象首先显示,然后当您 单击按钮时 它会循环显示 第二第三object.

但是我在遍历数据时遇到了问题,因为我不确定如何使用这个 JSON 结构--

  var data= {
    "Object_one":[
        {"date":"1/4/2010",
         "value":"50",},
        {"date":"6/22/2010",
         "value":"44",},
        {"date":"9/18/2010",
         "value":"42",},
    ],
    "Object_two":[
        {"date":"1/4/2010",
         "value":"54",},
        {"date":"6/22/2010",
         "value":"41",},
        {"date":"2012",
         "value":"42",},
    ],
    "Object_three":[
        {"date":"1/4/2010",
         "value":"55",},
        {"date":"6/22/2010",
         "value":"43",},
        {"date":"9/18/2010",
         "value":"65",},
    ]
}

我使用 underscore.js 设置了一个循环来遍历数据,但它只接收第一个数组的所有对象,而不是每个 array 中的第一个对象每个 对象 X.

https://jsfiddle.net/vw88/6Ljekv45/

(请参阅 js 的第 55 行,为矩形附加值的部分)

数据绑定到矩形的方式不正确:

var levels = levelsHolder.selectAll('rect.square-levels')
.data(data[key])

导致分配 data["Object one"],然后 data["Object two"] 等等,在第一次迭代中仅 data["Object one"] 输入 rects,即 3 个矩形,因为没有 [=使用 43=]update 方法,rects 保持原样,因为它们导致 3 个矩形对应于 data["Object one"] 数组元素。

一种解决方案是使用 data 并按如下方式映射数组的第一个元素:

var levels = levelsHolder.selectAll('rect.square-levels')
.data(Object.keys(data).map(function(k) { return data[k][0]; }))

现在,我很友善,也为您提供了按钮点击功能(开玩笑)。无论如何,我使用了两个变量 "initial" 和 "max",它们从 0 到数据中的最大数组长度,并相应地将绑定数据更改为矩形。是的,它也可以使用 underscore.js 来完成,但我在这里找不到它的需要。

点击按钮:

d3.select('#myButton').on('click', function() {
   initial++;
   if(initial > max) { initial = 0; }
   levels.data(Object.keys(data).map(function(k) { return data[k][initial]; }));

   drawSquares();
});

这是使用上述逻辑的代码片段(它不是最好的逻辑,但您可以根据需要更改它):

var data= {
 "Object one":[
  {"date":"2010",
   "value":"80",},
  {"date":"2011",
   "value":"94",},
  {"date":"2012",
   "value":"50",},
 ],
   "Object two":[
  {"date":"2010",
   "value":"104",},
  {"date":"2011",
   "value":"41",},
  {"date":"2012",
   "value":"92",},
 ],
   "Object three":[
  {"date":"2010",
   "value":"75",},
  {"date":"2011",
   "value":"43",},
  {"date":"2012",
   "value":"85",},
 ],
   "Object four":[
  {"date":"2010",
   "value":"75",},
  {"date":"2011",
   "value":"43",},
  {"date":"2012",
   "value":"85",},
 ]
}


  var margin = {top: 30, right: -3, bottom: 30, left:0},
  width = parseInt(d3.select('#holder').style('width'),10)
  width = width - margin.left - margin.right,
  height = width/2;
  
  var initial = 0, max = data['Object one'].length-1;

  var mainChartSVG = d3.select('#holder')
    .append('svg')
    .attr('width', width)
    .attr('height', height)

  var frameHolder = mainChartSVG.append('g')
    .classed('holder-frames',true);

  // Draw squares to show levels

  var maxValue = d3.max(data, function(d){
    return d.value;
  });

  var valueScale = d3.scale.linear()
    .domain([0,100])
    .range([50,0]);

  var levelsHolder = mainChartSVG.append('g')
    .classed('holder-levels',true);
    
  var levels = levelsHolder.selectAll('rect.square-levels')
    .data(Object.keys(data).map(function(k) { return data[k][initial]; }))
    .enter().append('rect')
    .classed('square-levels', true);
    
 function drawSquares() {
      levels
        .attr({
          x: function(d, i){
             return i % 5 * width/5
          },
          y: function(d, i){
             return valueScale(d.value)+(Math.floor(i / 5) * width/5)
          },
        width: width/5-3,
        height: function(d) {
          return (width/5-3)-valueScale(d.value) ;
        },
        fill:"red",
        class: function(d) { return d.value; }
    })
}
drawSquares();

var frameHolder = mainChartSVG.append('g')
    .classed('holder-frames',true);

  var keyarray = Object.keys(data)

  var frames = frameHolder.selectAll('rect.square-frame')
    .data(keyarray)
    .enter().append('rect')
    .classed('square-frame', true)
    .attr({
      x:function(d, i){
        //console.log(d, "D VALUE")
        return i % 5 * (width/5 )
      },
      y:function(d, i){
        return Math.floor(i / 5) * (width/5 )
      },
      width: width/5-3,
      height: width/5-3,
    })

d3.select('#myButton').on('click', function() {
 initial++;
  if(initial > max) { initial = 0; }
  levels.data(Object.keys(data).map(function(k) { return data[k][initial]; }));
  
 drawSquares();
});
body{
  background-color:white;
}

.square-frame{
  stroke: #38434f;
  fill: none;
}

a {
  text-decoration: none;
  display: inline-block;
  padding: 3px 8px;
  margin-bottom: 2em;
}

a:hover {
  background-color: gray;
  color: black;
}

#myButton {
  background-color: #e5e5e5;
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<a href="#" id="myButton">&#8250;</a>
<div id="holder"></div>

希望这对您有所帮助。如果您遇到任何问题,请告诉我。