GetJSON 从 URL 到 d3.js 图表
Posted
技术标签:
【中文标题】GetJSON 从 URL 到 d3.js 图表【英文标题】:GetJSON from URL into d3.js chart 【发布时间】:2018-10-22 12:41:45 【问题描述】:我正在尝试将 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);
任何帮助都会很棒!
【问题讨论】:
D3库中有json()
方法。
【参考方案1】:
我可以看到 $.getJSON 方法的问题,您正在尝试从 HTTP 加载数据,因此您可能会在 jsfiddle 控制台中收到混合内容错误,但尝试使用 http 服务器从本地计算机运行它,您将获取数据。
【讨论】:
freqData和freqData2有区别吗? 不,我认为它是一样的,但是你正在使用 ajax 调用,所以你需要在回调中执行仪表板 func -> d3.json('88.99.13.199:3000/dashboarddata', function(err, 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); ); // 在此处调用仪表板 );【参考方案2】:你的代码很好,但你有一些问题。
这是可以工作的代码。
查看 cmets 以了解您做错了什么。
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。
【讨论】:
以上是关于GetJSON 从 URL 到 d3.js 图表的主要内容,如果未能解决你的问题,请参考以下文章