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

时间:2018-02-13 08:10:58

标签: javascript arrays loops d3.js underscore.js

D3d.js 中,我正在尝试为数组中的每个对象附加矩形,因此矩形的高度由值决定。此外,我正在努力使它只显示每个数组中的第一个对象,然后当您单击按钮时,它会循环显示 2nd < / strong>和 第三次 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中的第一个对象strong> 对象X

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

(请参阅js的第55行,了解使用值附加矩形的部分)

1 个答案:

答案 0 :(得分:1)

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

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

导致分配data["Object one"],然后分配data["Object two"]等等,在第一次迭代中仅rects输入data["Object one"],即3个rects,因为没有更新使用的方法,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到最大数组长度,并相应地将绑定数据更改为rects。是的,它可以使用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>

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