GetJSON从URL到d3.js图表

时间:2018-05-12 06:22:23

标签: javascript jquery json parsing d3.js

我正在尝试将json加载到我的d3.js图表​​中。我首先尝试使用静态硬编码的虚拟json(freqData)工作正常,但是当我尝试从URL(freqData2)重现json时,图表不会被创建,因为它无法读取我的json。我看到结构或变量名称没有差异。

你可以看看这个jsfiddle(不要注意图表本身,它在我的jsfiddle中有点乱,但在我的真实代码中它可以正确使用正确的数据)。 https://jsfiddle.net/liostse/yfw3zgdL/2/

function dashboard(id, fData) { /*Creating dashboard for priorities*/
  var barColor = 'steelblue';

  function segColor(c) {
    return {
      P2: "#807dba",
      P3: "#e08214",
      P4: "#41ab5d",
      P5: "#1dc609",
      P6: "#f7f322"
    }[c];
  }
  // compute total for each state.
  fData.forEach(function(d) {
    console.log(d.freq.P2);
    d.total = d.freq.P2 + d.freq.P3 + d.freq.P4 + d.freq.P5 + d.freq.P6;
    console.log(d.total);
  });
  // function to handle histogram.
  function histoGram(fD) {
    var hG = {},
      hGDim = {
        t: 30,
        r: 30,
        b: 20,
        l: 50
      };
    hGDim.w = 600 - hGDim.l - hGDim.r,
      hGDim.h = 300 - hGDim.t - hGDim.b;
    //create svg for histogram.
    var hGsvg = d3.select(id).append("svg")
      .attr("width", hGDim.w + hGDim.l + hGDim.r)
      .attr("height", hGDim.h + hGDim.t + hGDim.b).append("g")
      .attr("transform", "translate(" + hGDim.l + "," + hGDim.t + ")");
    // create function for x-axis mapping.
    var x = d3.scale.ordinal().rangeRoundBands([0, hGDim.w], 0.1)
      .domain(fD.map(function(d) {
        return d[0];
      }));
    // Add x-axis to the histogram svg.
    hGsvg.append("g").attr("class", "x axis")
      .attr("transform", "translate(0," + hGDim.h + ")")
      .call(d3.svg.axis().scale(x).orient("bottom"));
    // Create function for y-axis map.
    var y = d3.scale.linear().range([hGDim.h, 0])
      .domain([0, d3.max(fD, function(d) {
        return d[1];
      })]);
    // Create bars for histogram to contain rectangles and freq labels.
    var bars = hGsvg.selectAll(".bar").data(fD).enter()
      .append("g").attr("class", "bar");
    //create the rectangles.
    bars.append("rect")
      .attr("x", function(d) {
        return x(d[0]);
      })
      .attr("y", function(d) {
        return y(d[1]);
      })
      .attr("width", x.rangeBand())
      .attr("height", function(d) {
        return hGDim.h - y(d[1]);
      })
      .attr('fill', barColor)
      .on("mouseover", mouseover) // mouseover is defined below.
      .on("mouseout", mouseout); // mouseout is defined below.
    //Create the frequency labels above the rectangles.
    bars.append("text").text(function(d) {
        return d3.format(",")(d[1])
      })
      .attr("x", function(d) {
        return x(d[0]) + x.rangeBand() / 2;
      })
      .attr("y", function(d) {
        return y(d[1]) - 5;
      })
      .attr("text-anchor", "middle");

    function mouseover(d) { // utility function to be called on mouseover.
      // filter for selected state.
      var st = fData.filter(function(s) {
          return s.State == d[0];
        })[0],
        nD = d3.keys(st.freq).map(function(s) {
          return {
            type: s,
            freq: st.freq[s]
          };
        });
      // call update functions of pie-chart and legend.    
      pC.update(nD);
      leg.update(nD);
    }

    function mouseout(d) { // utility function to be called on mouseout.
      // reset the pie-chart and legend.    
      pC.update(tF);
      leg.update(tF);
    }
    // create function to update the bars. This will be used by pie-chart.
    hG.update = function(nD, color) {
      // update the domain of the y-axis map to reflect change in frequencies.
      y.domain([0, d3.max(nD, function(d) {
        return d[1];
      })]);
      // Attach the new data to the bars.
      var bars = hGsvg.selectAll(".bar").data(nD);
      // transition the height and color of rectangles.
      bars.select("rect").transition().duration(500)
        .attr("y", function(d) {
          return y(d[1]);
        })
        .attr("height", function(d) {
          return hGDim.h - y(d[1]);
        })
        .attr("fill", color);
      // transition the frequency labels location and change value.
      bars.select("text").transition().duration(500)
        .text(function(d) {
          return d3.format(",")(d[1])
        })
        .attr("y", function(d) {
          return y(d[1]) - 5;
        });
    }
    return hG;
  }
  // function to handle pieChart.
  function pieChart(pD) {
    var pC = {},
      pieDim = {
        w: 250,
        h: 250
      };
    pieDim.r = Math.min(pieDim.w, pieDim.h) / 2;
    // create svg for pie chart.
    var piesvg = d3.select(id).append("svg")
      .attr("width", pieDim.w).attr("height", pieDim.h).append("g")
      .attr("transform", "translate(" + pieDim.w / 2 + "," + pieDim.h / 2 + ")");
    // create function to draw the arcs of the pie slices.
    var arc = d3.svg.arc().outerRadius(pieDim.r - 10).innerRadius(0);
    // create a function to compute the pie slice angles.
    var pie = d3.layout.pie().sort(null).value(function(d) {
      return d.freq;
    });
    // Draw the pie slices.
    piesvg.selectAll("path").data(pie(pD)).enter().append("path").attr("d", arc)
      .each(function(d) {
        this._current = d;
      })
      .style("fill", function(d) {
        return segColor(d.data.type);
      })
      .on("mouseover", mouseover).on("mouseout", mouseout);
    // create function to update pie-chart. This will be used by histogram.
    pC.update = function(nD) {
      piesvg.selectAll("path").data(pie(nD)).transition().duration(500)
        .attrTween("d", arcTween);
    }
    // Utility function to be called on mouseover a pie slice.
    function mouseover(d) {
      // call the update function of histogram with new data.
      hG.update(fData.map(function(v) {
        return [v.measure_code, v.freq[d.data.type]];
      }), segColor(d.data.type));
    }
    //Utility function to be called on mouseout a pie slice.
    function mouseout(d) {
      // call the update function of histogram with all data.
      hG.update(fData.map(function(v) {
        return [v.measure_code, v.total];
      }), barColor);
    }
    // Animating the pie-slice requiring a custom function which specifies
    // how the intermediate paths should be drawn.
    function arcTween(a) {
      var i = d3.interpolate(this._current, a);
      this._current = i(0);
      return function(t) {
        return arc(i(t));
      };
    }
    return pC;
  }
  // function to handle legend.
  function legend(lD) {
    var leg = {};
    // create table for legend.
    var legend = d3.select(id).append("table").attr('class', 'legend');
    // create one row per segment.
    var tr = legend.append("tbody").selectAll("tr").data(lD).enter().append("tr");
    // create the first column for each segment.
    tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect")
      .attr("width", '16').attr("height", '16')
      .attr("fill", function(d) {
        return segColor(d.type);
      });
    // create the second column for each segment.
    tr.append("td").text(function(d) {
      return d.type;
    });
    // create the third column for each segment.
    tr.append("td").attr("class", 'legendFreq')
      .text(function(d) {
        return d3.format(",")(d.freq);
      });
    // create the fourth column for each segment.
    tr.append("td").attr("class", 'legendPerc')
      .text(function(d) {
        return getLegend(d, lD);
      });
    // Utility function to be used to update the legend.
    leg.update = function(nD) {
      // update the data attached to the row elements.
      var l = legend.select("tbody").selectAll("tr").data(nD);
      // update the frequencies.
      l.select(".legendFreq").text(function(d) {
        return d3.format(",")(d.freq);
      });
      // update the percentage column.
      l.select(".legendPerc").text(function(d) {
        return getLegend(d, nD);
      });
    }

    function getLegend(d, aD) { // Utility function to compute percentage.
      return d3.format("%")(d.freq / d3.sum(aD.map(function(v) {
        return v.freq;
      })));
    }
    return leg;
  }
  // calculate total frequency by segment for all state.
  var tF = ['P2', 'P3', 'P4', 'P5', 'P6'].map(function(d) {
    return {
      type: d,
      freq: d3.sum(fData.map(function(t) {
        return t.freq[d];
      }))
    };
  });
  // calculate total frequency by state for all segment.
  var sF = fData.map(function(d) {
    return [d.measuer_code, d.total];
  });
  var hG = histoGram(sF), // create the histogram.
    pC = pieChart(tF), // create the pie-chart.
    leg = legend(tF); // create the legend.
}
freqData2 = [];
$.getJSON('http://88.99.13.199:3000/dashboarddata', function(mydata) {
  mydata.forEach(function(val) {
    var freqData1 = {};
    freqData1["measure_code"] = val.measure_code;
    freqData1["freq"] = {
      P2: val.p2,
      P3: val.p3,
      P4: val.p4,
      P5: val.p5,
      P6: val.p6
    };
    freqData2.push(freqData1);
  });
  return freqData2;
});
var freqData = [{
  measure_code: 'Μ1',
  freq: {
    P2: 47,
    P3: 19,
    P4: 29,
    P5: 20,
    P6: 100
  }
}, {
  measure_code: 'Μ2',
  freq: {
    P2: 11,
    P3: 42,
    P4: 74,
    P5: 15,
    P6: 10
  }
}, {
  measure_code: 'Μ3',
  freq: {
    P2: 93,
    P3: 21,
    P4: 48,
    P5: 10,
    P6: 10
  }
}, {
  measure_code: 'Μ4',
  freq: {
    P2: 82,
    P3: 11,
    P4: 12,
    P5: 50,
    P6: 20
  }
}, {
  measure_code: 'Μ5',
  freq: {
    P2: 44,
    P3: 34,
    P4: 98,
    P5: 10,
    P6: 14
  }
}, {
  measure_code: 'Μ6',
  freq: {
    P2: 19,
    P3: 17,
    P4: 13,
    P5: 10,
    P6: 10
  }
}, {
  measure_code: 'Μ7',
  freq: {
    P2: 18,
    P3: 27,
    P4: 12,
    P5: 50,
    P6: 18
  }
}, {
  measure_code: 'Μ8',
  freq: {
    P2: 48,
    P3: 38,
    P4: 42,
    P5: 15,
    P6: 17
  }
}, {
  measure_code: 'Μ9',
  freq: {
    P2: 77,
    P3: 18,
    P4: 15,
    P5: 50,
    P6: 14
  }
}, {
  measure_code: 'Μ10',
  freq: {
    P2: 162,
    P3: 39,
    P4: 41,
    P5: 40,
    P6: 10
  }
}, {
  measure_code: 'Μ11',
  freq: {
    P2: 62,
    P3: 39,
    P4: 41,
    P5: 15,
    P6: 20
  }
}, {
  measure_code: 'Μ12',
  freq: {
    P2: 12,
    P3: 39,
    P4: 41,
    P5: 15,
    P6: 12
  }
}, {
  measure_code: 'Μ13',
  freq: {
    P2: 162,
    P3: 39,
    P4: 71,
    P5: 30,
    P6: 10
  }
}, {
  measure_code: 'Μ14',
  freq: {
    P2: 62,
    P3: 79,
    P4: 41,
    P5: 15,
    P6: 12
  }
}, {
  measure_code: 'Μ16',
  freq: {
    P2: 12,
    P3: 39,
    P4: 41,
    P5: 10,
    P6: 10
  }
}, {
  measure_code: 'Μ19',
  freq: {
    P2: 16,
    P3: 379,
    P4: 41,
    P5: 10,
    P6: 10
  }
}, {
  measure_code: 'Μ20',
  freq: {
    P2: 16,
    P3: 39,
    P4: 41,
    P5: 50,
    P6: 32
  }
}, {
  measure_code: 'Μ97',
  freq: {
    P2: 62,
    P3: 379,
    P4: 47,
    P5: 50,
    P6: 10
  }
}];
console.log(typeof freqData2);
console.log(typeof freqData2);
dashboard('#dashboard', freqData);

任何帮助都会很精彩!

2 个答案:

答案 0 :(得分:0)

我可以看到$ .getJSON方法的问题,你试图从HTTP加载数据,所以你可能在jsfiddle控制台中得到混合内容错误,但尝试使用http服务器从本地机器运行它,你将得到数据。

答案 1 :(得分:0)

您的代码很好但是您遇到了一些问题。

以下是可行的代码。

查看评论以了解您做错了什么。

var freqData2 = []; //You didn't declared a var

//Use d3.json instead of jquery.getJSON
//As also suggested by @Alexandra in the comments
d3.json('http://88.99.13.199:3000/dashboarddata', function(err, mydata) {

 console.log(err);

 if(mydata && mydata.length > 0) {
 //if mydata is defined and have data then loop

 mydata.forEach(function(val) {
    var freqData1 = {};
    freqData1["measure_code"] = val.measure_code;
    freqData1["freq"] = {
      P2: val.p2,
      P3: val.p3,
      P4: val.p4,
      P5: val.p5,
      P6: val.p6
    };

    freqData2.push(freqData1);
  });
}  
  return freqData2;
});

//Timeout? WHY? because it takes time for url to respond back 
//and then all that data manipulation on it. 
//So, we will wait 1 Second to get data back and then we will print it.

setTimeout(()=>{
dashboard('#dashboard', freqData2);
},1000);

其他问题是您在JSfiddle中遇到混合内容错误。为什么?因为你试图从HTTP获取数据,因为默认情况下JSFiddle会转到HTTPS。