简体   繁体   中英

D3JS passing in a JSON object returns an error

This is my code:

d3.json('../../dev/json/ajson.php', function (error, json) {
  if (error) return console.warn(error);

  megavalues = ["Meetings", "Development", "Management"];
  megadata = [213, 891, 121];

  var categoryGraph = d3.select('#graph-container').append('svg')
      .attr('width', graphWidth)
      .attr('height', graphHeight)
      .data(megadata)
      .append('svg:g')
      .attr('transform', 'translate(' + graphWidth / 2.085 + ',' + graphHeight / 2.085 + ')');

  var arc = d3.svg.arc()
      .outerRadius(graphRadius - 10)
      .innerRadius(graphRadius - 130);

  var pie = d3.layout.pie()
      .value(function(d){ return d });

  var categoryDataGraph = categoryGraph.selectAll('g.slice')
      .data(pie(megadata))
      .enter().append('svg:g')
      .attr('class', 'slice');

  categoryDataGraph.append('svg:path')
      .attr('fill', function(d, i){ return color(i); })
      .attr('d', arc);

  categoryDataGraph.append('text')
      .attr('transform', function(d) { return 'translate(' + arc.centroid(d) + ')' })
      .attr('dy', '.35em')
      .attr('text-anchor', 'middle')
      .text(function(d, i) { return megavalues[i]; });

This is the result:

http://cloud.erikhellman.com/eQHJ/5TmsqKWu

This is my problem:

I am currently drawing the graphs using 2 arrays (megavalues & megadata), but what I WANT to do is to draw it onto categoryGraph using this json object:

json.projectData.timeDistribution

which looks like this:

Object {Meetings: 12, Planning: 1, Development: 21} 

However, when I pass the object as the data the graph isn't drawn and/or returns this error:

Uncaught TypeError: Object #<Object> has no method 'map'

I have spent the past 5 hours reading through the documentation and googling for help. This is the first time I am using D3.js and this far surpasses my JavaScript knowledge I think. On all the examples I have found there has either been arrays passed that only consisted of numbers or if there has been text included, the JSON has looked different. But I am sure it has to work even with my JSON object looking like this, right?

This is my first question here, if I can improve the question or improve anything here in any way, please tell me. :)

The "secret sauce" here is how you access the values in what's passed in. The difference between the two structures that you've tried is that one is an array (and works), whereas the other one is an object (and doesn't). This is because D3 won't iterate over an object (as suggested by the error message).

The easiest way to fix this is to transform your object into an array using d3.entries and changing the accessor function accordingly. That is, your code would look something like

var pie = d3.layout.pie()
  .value(function(d) { return d.value; });

var categoryDataGraph = categoryGraph.selectAll('g.slice')
  .data(pie(d3.entries(json.projectData.timeDistribution))
  .enter().append('svg:g')
  .attr('class', 'slice');

You then also need to change the way the text is created:

categoryDataGraph.append('text')
  .attr('transform', function(d) { return 'translate(' + arc.centroid(d) + ')' })
  .attr('dy', '.35em')
  .attr('text-anchor', 'middle')
  .text(function(d, i) { return d3.keys(json.projectData.timeDistribution)[i]; });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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