【问题标题】:D3.js: create a fixed number of elementsD3.js:创建固定数量的元素
【发布时间】:2016-08-23 10:26:36
【问题描述】:

我正在尝试使用 D3 创建固定数量的元素,并从 json 文件中获取该值。这意味着,如果给定的 json 数据是 n,我想将 n 元素打印到我的 svg 中。

这是我的代码:

    // Defining the size of the svg element
    var w = 1000;
    var h = 50;

    // Defining the dataset
    d3.json("people.json", function(dataset) {

    // Iterating through the json
    for(var i=0; i<dataset.length; i++) {

                var svg = d3.select("body").append("svg")
                    .attr("width", w)
                    .attr("height", h);

            // Iterating through the value
            for(var j=0; j<dataset[i].age; j++) {

                svg.selectAll("rect")
                        .data(dataset)
                        .enter()
                        .append("rect")
                        .attr("width", 20)
                        .attr("height", 20)
                        .attr("x", function(d, j) { return j * 55 })
            }

        }

    });

这是我的 json 示例文件(年龄的完全随机值):

  [{
    "name": "Larry",
    "last": "Page",
    "country": "USA",
    "city": "Mountain View",
    "age": 32
  }, {
    "name": "Sergey",
    "last": "Bean",
    "country": "USA",
    "city": "Mountain View",
    "age": 37
  }, {
    "name": "Bill",
    "last": "Gates",
    "country": "USA",
    "city": "Seattle",
    "age": 60
  }, {
    "name": "Mark",
    "last": "Zuckemberg",
    "country": "USA",
    "city": "Palo Alto",
    "age": 35
  }, {
    "name": "Sergio",
    "last": "Marchionne",
    "country": "Italy",
    "city": "Milan",
    "age": 65
  }
]

我的预期结果应该是这样的([-] --> svg rectangle)

  1. 拉里·佩奇: [-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][- ][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-]

  2. 谢尔盖·比恩: [-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][- ][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][ -][-]

等等……

你能帮我理解我做错了什么吗?

谢谢!

【问题讨论】:

  • 只需从矩形绘图中删除.data(dataset)。那是放错地方了。
  • 感谢您的回答。但是删除它会导致此错误:get_data_from_json.html?_ijt=4057q09d7k7p7tej2g0mf5objt:56 Uncaught TypeError: svg.selectAll(...).enter is not a function(anonymous function) @ get_data_from_json.html?
  • 让我免费给您一个建议:每次您考虑在 D3 可视化中使用 fior 循环时,问问自己:“这有必要吗?”。在 98.7℅ 的情况下,没有必要(来源:FakeData Inc.)
  • selectAll 也放错了位置,例如 enter()。你只需要append("rect") 并设置它的属性。
  • 这个名字是“象形图”。这是 d3 中的一项非常基本的任务,无需单个 for 循环即可创建您想要的内容。现在我在我的手机上,写起来很糟糕,但我相信很快就会有人向你展示如何做到这一点。

标签: javascript json d3.js svg


【解决方案1】:

纯粹的 D3 方法根本不需要 for 循环(就像 Gerardo Furtado 在他的 comment 中提到的那样),并且将类似于以下内容:

d3.select("body").selectAll("svg")
  .data(dataset)              // Bind the entire dataset
  .enter().append("svg")      // Append one svg per object in dataset
  .selectAll("rect")
    .data(function(d) {       // Inherit data from svg by mapping of objects
      // Create an array of number of required rects
      return d3.range(d.age).map(function(d) { return d*15; }); 
    })
    .enter().append("rect")   // Append rects per svg
      .attr("x", function(d) {
        return d;             // Position was calculated in above mapping in data()
      });

这就是绘制您所追求的图形所需的全部内容(属性放在一边)。有关设置所有值的完整示例,请查看以下示例:

var dataset =   [{
    "name": "Larry",
    "last": "Page",
    "country": "USA",
    "city": "Mountain View",
    "age": 32
  }, {
    "name": "Sergey",
    "last": "Bean",
    "country": "USA",
    "city": "Mountain View",
    "age": 37
  }, {
    "name": "Bill",
    "last": "Gates",
    "country": "USA",
    "city": "Seattle",
    "age": 60
  }, {
    "name": "Mark",
    "last": "Zuckemberg",
    "country": "USA",
    "city": "Palo Alto",
    "age": 35
  }, {
    "name": "Sergio",
    "last": "Marchionne",
    "country": "Italy",
    "city": "Milan",
    "age": 65
  }
];

// Defining the size of the svg element
var w = 1000;
var h = 50;

// Defining the dataset
//d3.json("people.json", function(dataset) {

  d3.select("body")
    .selectAll("svg")
    .data(dataset)              // Bind the entire dataset
    .enter().append("svg")      // Append one svg per object in dataset
      .attr("width", w)
      .attr("height", h)
    .selectAll("rect")
      .data(function(d) {       // Inherit data from svg by mapping of objects
        // Create an array of number of required rects
        return d3.range(d.age).map(function(d) { return d*15; }); 
      })
      .enter().append("rect")   // Append rects per svg
        .attr("width", 10)
        .attr("height",10)
        .attr("x", function(d) {
          return d;             // Position was calculated in above mapping in data()
        });


//});
&lt;script src="https://d3js.org/d3.v4.js"&gt;&lt;/script&gt;

【讨论】:

    【解决方案2】:

    你可以这样做:

    var dataset = [{
      "name": "Larry",
      "last": "Page",
      "country": "USA",
      "city": "Mountain View",
      "age": 32
    }, {
      "name": "Sergey",
      "last": "Bean",
      "country": "USA",
      "city": "Mountain View",
      "age": 37
    }, {
      "name": "Bill",
      "last": "Gates",
      "country": "USA",
      "city": "Seattle",
      "age": 60
    }, {
      "name": "Mark",
      "last": "Zuckemberg",
      "country": "USA",
      "city": "Palo Alto",
      "age": 35
    }, {
      "name": "Sergio",
      "last": "Marchionne",
      "country": "Italy",
      "city": "Milan",
      "age": 65
    }];
    
    // Defining the size of the svg element
    var w = 1000;
    var h = 500;
    var itemH = 10;
    var itemW = 3;
    var padding = 2;
    
    
    // Append svg element
    var svg = d3.select("body").append("svg")
      .attr("width", w)
      .attr("height", h);
    
    // Append groups for each in dataset
    var group = svg.selectAll("g")
      .data(dataset)
      .enter()
      .append('g');
    
    // Each group
    group.each(function(d, i) {
    
      //console.log(d);
      var age = d.age;
    
      var self = d3.select(this);
    
      // Transform the group in Y
      self.attr('transform', function() {
        return 'translate(0,' + (i * (itemH + padding)) + ')';
      });
    
      // Append rect forEach from 0 - age
      d3.range(age).forEach(function(i) {
        //console.log(i);
    
        self.append('rect')
          .attr('width', itemW)
          .attr('height', itemH)
          .attr('x', function() {
            return i * (itemW + padding);
          });
      });
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    
    
    <body></body>

    【讨论】:

    • 吹毛求疵,但 D3 循环的方式是函数式的,即d3.range(age).each(function(d, i){ ... })
    • @Duopixel 你是说 forEach 吗?很好,我已将其添加到我的答案中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 2016-05-05
    相关资源
    最近更新 更多