繁体   English   中英

D3.js遍历对象数组

[英]D3.js looping through an array of objects

我正在尝试根据标题制作一排高度和宽度相等的条形图。 有一个100个对象的数组,每个对象包含一个称为result ,它本身和其他20个对象的数组,因此最终结果必须是一行2000条,但是我只能得到20条:

错误的输出

Codepen: https ://codepen.io/ekilja01/pen/RdJqGO

数据是一个对象数组,具有一个称为result的对象数组,格式如下:

0:
page: 1
results: Array(20)
0: {vote_count: 17968, id: 19995, video: false, vote_average: 7.4, title: "Avatar", …}
...
length: 20

1: {page: 2, total_results: 406130, total_pages: 20307, results: Array(20)}
2: {page: 3, total_results: 406130, total_pages: 20307, results: Array(20)}

这是我的方法:

d3.json('data.json').then(data => {

  console.log(data);
  for (let i = 0; i < data.length; i++) {


    //x and y domain
    xScale.domain(data[i].results.map(d => d.title));
    yScale.domain(data[i].results.map(d => d.original_title));

    svg.selectAll('rect')
      .data(data[i].results)
      .enter()
      .append('rect')
      .style('fill', 'red')
      .attr('width', xScale.bandwidth())
      .attr('height', 70)
      .attr('x', function (d) {
        return xScale(d.title);
      })
      .attr('y', function (d) {
        return yScale.bandwidth() + 175;
      });

  }
}).catch(error => console.log(error));

精美的问题描述和CodePen-轻松帮助您!

我已经为您的CodePen链接做了一个稍微修改的版本

基本上,发生的事情是,对于for循环中的每个迭代,您都将选择前x个(在您的情况下为20个)匹配的rect元素。 这意味着在第一次迭代之后,每次迭代都将使用当前迭代的20个数据条目替换与相同的20个rect元素的数据绑定。

我进行了两种更改来解决此问题:

  1. svg.selectAll('rect')更改为svg.selectAll('.rect_${i}') ,这将选择具有相应类( .rect_0.rect_1等)的所有元素。 这样做可以防止覆盖先前的rect元素。
  2. .attr('x')的回调函数中添加+ xScale.range()[1] * i 这会将每20个rect元素向右移动,以确保rect元素不会相互绘制。

但是,要点2确实可以绘制出非常宽的图表。 如果您希望各行之间彼此相邻,我使用rect元素的高度添加了功能(在注释中)。

让我知道这是否对您有帮助!

在循环中,仅在循环中第一次添加元素:数据数组中有20个项目,svg中没有矩形,因此输入了全部20个项目。 第二次在数据数组中有20个项目,在svg中有20个矩形,因此enter选择为空,新数据仅绑定到20个现有矩形。

作为其他答案的替代方法,您的数据似乎不是分层的,但是您具有分层的结构。 如果您的数据结构与DOM结构相同,那么这将更加简单。 让我们对数据进行一些重组:

var combined = [];
for (let i = 0; i < data.length; i++) {
  combined.push(...data[i].results);
}

现在我们的数据是:

[
  {vote_count: 17968, id: 19995, video: false, vote_average: 7.4, title: "Avatar", …,}
  {...},
  {...},
  ...

并且所有要映射的对象都在一个数组中,该数组中的一项,一个要添加到图表中的元素。 现在我们可以做一个简单的输入循环:

svg.selectAll('rect')
  .data(combined)
  .enter()
  .append('rect')
  .style('fill', 'red')
  .attr('width', xScale.bandwidth())
  .attr('height', 70)
  .attr('x', function (d) {
    return xScale(d.title);
  })
  .attr('y', function (d) {
    return yScale.bandwidth() + 175;
  });

通常,如果需要循环以在DOM中输入元素,则无需使用惯用的d3。 通过避免for循环输入元素,缩放也变得更加容易,因为在遍历父数组时我们不会不断更新它。 比例域和范围只需设置一次。

这是更新的codepen

现在,2000个元素将生成非常小的矩形,可能小于一个像素宽,我不确定为什么要像这样缩放条形的高度,但这是不同的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM