如何解决Javascript D3饼图不会从具有字典列表的JSON文件中提取数据
我有一个包含数据的.json文件,我想从中制作一个d3甜甜圈(饼图)图表。我不是特别精通javascript,每个示例我都可以发现从内嵌json数据中提取的内容或json文件的结构与我的不同(mine是字典列表;它们通常是单个字典)。我已经进行了几天的故障排除,以某种方式无法解决任何实际可行的问题。有什么想法/提示吗?
https://www.d3-graph-gallery.com/graph/donut_label.html的示例使用内联json数据呈现带有标签的甜甜圈图。我试图通过以下方式修改该代码:
- 从/data/all-facet-digitized.json中提取json数据
- 拉标签每个词典的“ facet”键(“ true”和“ false”),以及每个词典的“ count”键的值(373977和55433)。
- 更改色标域以匹配构面键(“ true”和“ false”)
/data/all-facet-digitized.json看起来像:
$ node repro.js
logged { [Error: EROFS: read-only file system,open '/test.txt'] errno: -30,code: 'EROFS',syscall: 'open',path: '/test.txt' }
我的html文件中的代码如下:
[
{
"count": "55433","facet": "true"
},{
"count": "373977","facet": "false"
}
]
我的结果呈现为空白:
<div id="chart"></div> <!-- div containing the donut chart -->
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
// set the dimensions and margins of the graph
var width = 450
height = 450
margin = 40
// The radius of the pieplot is half the width or half the height (smallest one) minus margin.
var radius = Math.min(width,height) / 2 - margin
// append the svg object to the div called 'chart'
var svg = d3.select("#chart")
.append("svg")
.attr("width",width)
.attr("height",height)
.append("g")
.attr("transform","translate(" + width / 2 + "," + height / 2 + ")");
// Parse the Data
d3.json("/data/all-facet-digitized.json",function(data) {
// set the color scale
var color = d3.scaleOrdinal()
.domain(["true","false"])
.range(d3.schemeDark2);
// Compute the position of each group on the pie:
var pie = d3.pie()
.sort(null) // Do not sort group by size
.value(function(d) {return d.count; })
var data_ready = pie(d3.entries(data))
// The arc generator
var arc = d3.arc()
.innerRadius(radius * 0.5) // This is the size of the donut hole
.outerRadius(radius * 0.8)
// Another arc that won't be drawn. Just for labels positioning
var outerArc = d3.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9)
// Build the pie chart: Basically,each part of the pie is a path that we build using the arc function.
svg
.selectAll('allSlices')
.data(data_ready)
.enter()
.append('path')
.attr('d',arc)
.attr('fill',function(d){ return(color(d.facet)) })
.attr("stroke","white")
.style("stroke-width","2px")
.style("opacity",0.7)
// Add the polylines between chart and labels:
svg
.selectAll('allPolylines')
.data(data_ready)
.enter()
.append('polyline')
.attr("stroke","black")
.style("fill","none")
.attr("stroke-width",1)
.attr('points',function(d) {
var posA = arc.centroid(d) // line insertion in the slice
var posB = outerArc.centroid(d) // line break: we use the other arc generator that has been built only for that
var posC = outerArc.centroid(d); // Label position = almost the same as posB
var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2 // we need the angle to see if the X position will be at the extreme right or extreme left
posC[0] = radius * 0.95 * (midangle < Math.PI ? 1 : -1); // multiply by 1 or -1 to put it on the right or on the left
return [posA,posB,posC]
})
// Add the polylines between chart and labels:
svg
.selectAll('allLabels')
.data(data_ready)
.enter()
.append('text')
.text( function(d) { console.log(d.facet) ; return d.facet} )
.attr('transform',function(d) {
var pos = outerArc.centroid(d);
var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
pos[0] = radius * 0.99 * (midangle < Math.PI ? 1 : -1);
return 'translate(' + pos + ')';
})
.style('text-anchor',function(d) {
var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
return (midangle < Math.PI ? 'start' : 'end')
})
})
</script>
解决方法
schemeDark2
在d3 v4中不存在。我已将其替换为schemeCategory10
:
var color = d3.scaleOrdinal()
.domain(["true","false"])
.range(d3.schemeCategory10);
由于您具有对象数组,因此不需要d3.entries
。这需要一个对象并将其转换为一个数组,其中每个键都是该数组的一项。但是由于这里已经有了一个数组,因此可以直接将其放在pie()
中:
// Compute the position of each group on the pie:
var pie = d3.pie()
.sort(null) // Do not sort group by size
.value(function(d) {return d.count; })
var data_ready = pie(data)
现在您已经有了数据,您可以在任何功能上访问它:尝试将console.log(data_ready)
放到可用的位置。您会看到数据绑定为每个对象的.data
属性。 pie()
接受一个数组,并将其放入一种便于制作饼图的格式。
假设我们要访问facet属性:我们将其作为item.data.facet
进行访问。因此,在您要访问的功能中,您可以执行以下操作:
svg
.selectAll('allSlices')
.data(data_ready)
.enter()
.append('path')
.attr('d',arc)
.attr('fill',function(d){ return(color(d.data.facet)) })
<head></head>
<div id="chart"></div> <!-- div containing the donut chart -->
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
// set the dimensions and margins of the graph
var width = 450
height = 450
margin = 40
// The radius of the pieplot is half the width or half the height (smallest one) minus margin.
var radius = Math.min(width,height) / 2 - margin
// append the svg object to the div called 'chart'
var svg = d3.select("#chart")
.append("svg")
.attr("width",width)
.attr("height",height)
.append("g")
.attr("transform","translate(" + width / 2 + "," + height / 2 + ")");
// Parse the Data
var data = [
{
"count": "55433","facet": "true"
},{
"count": "373977","facet": "false"
}
]
// set the color scale
var color = d3.scaleOrdinal()
.domain(["true","false"])
.range(d3.schemeCategory10);
// Compute the position of each group on the pie:
var pie = d3.pie()
.sort(null) // Do not sort group by size
.value(function(d) {return d.count; })
var data_ready = pie(data)
console.log('data_r',data_ready)
// The arc generator
var arc = d3.arc()
.innerRadius(radius * 0.5) // This is the size of the donut hole
.outerRadius(radius * 0.8)
// Another arc that won't be drawn. Just for labels positioning
var outerArc = d3.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9)
// Build the pie chart: Basically,each part of the pie is a path that we build using the arc function.
svg
.selectAll('allSlices')
.data(data_ready)
.enter()
.append('path')
.attr('d',arc)
.attr('fill',function(d){ return(color(d.data.facet)) })
.attr("stroke","white")
.style("stroke-width","2px")
.style("opacity",0.7)
// Add the polylines between chart and labels:
svg
.selectAll('allPolylines')
.data(data_ready)
.enter()
.append('polyline')
.attr("stroke","black")
.style("fill","none")
.attr("stroke-width",1)
.attr('points',function(d) {
var posA = arc.centroid(d) // line insertion in the slice
var posB = outerArc.centroid(d) // line break: we use the other arc generator that has been built only for that
var posC = outerArc.centroid(d); // Label position = almost the same as posB
var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2 // we need the angle to see if the X position will be at the extreme right or extreme left
posC[0] = radius * 0.95 * (midangle < Math.PI ? 1 : -1); // multiply by 1 or -1 to put it on the right or on the left
return [posA,posB,posC]
})
// Add the polylines between chart and labels:
svg
.selectAll('allLabels')
.data(data_ready)
.enter()
.append('text')
.text( function(d) { return d.data.facet} )
.attr('transform',function(d) {
var pos = outerArc.centroid(d);
var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
pos[0] = radius * 0.99 * (midangle < Math.PI ? 1 : -1);
return 'translate(' + pos + ')';
})
.style('text-anchor',function(d) {
var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
return (midangle < Math.PI ? 'start' : 'end')
})
</script>
,
好的,这里的问题是您完全错过了在转换JSON响应后data_ready
的结构。您可能希望在设置console.log(data_ready)
之后立即添加data_ready
并在控制台中对其进行检查,以更好地理解以下修补程序。
首先进行颜色修复:
.attr('fill',function(d){ return(color(d.data.value.facet)) })
然后进行数据修复:
.value(function(d) {return d.value.count; })
最后是标签修复:
.text( function(d) { console.log(d.data.key) ; return d.data.value.facet } )
您的脚本应如下所示:
// set the dimensions and margins of the graph
var width = 450
height = 450
margin = 40
// The radius of the pieplot is half the width or half the height (smallest one). I subtract a bit of margin.
var radius = Math.min(width,height) / 2 - margin
// append the svg object to the div called 'my_dataviz'
var svg = d3.select("#chart")
.append("svg")
.attr("width",width)
.attr("height",height)
.append("g")
.attr("transform"," + height / 2 + ")");
d3.json("/data/all-facet-digitized.json",function(data) {
// set the color scale
var color = d3.scaleOrdinal()
.domain(["true","false"])
.range(d3.schemeDark2);
// Compute the position of each group on the pie:
var pie = d3.pie()
.sort(null) // Do not sort group by size
.value(function(d) {return d.value.count; })
var data_ready = pie(d3.entries(data))
// The arc generator
var arc = d3.arc()
.innerRadius(radius * 0.5) // This is the size of the donut hole
.outerRadius(radius * 0.8)
// Another arc that won't be drawn. Just for labels positioning
var outerArc = d3.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9)
// Build the pie chart: Basically,each part of the pie is a path that we build using the arc function.
svg
.selectAll('allSlices')
.data(data_ready)
.enter()
.append('path')
.attr('d',arc)
.attr('fill',function(d){ return(color(d.data.value.facet)) })
.attr("stroke","white")
.style("stroke-width","2px")
.style("opacity",0.7)
// Add the polylines between chart and labels:
svg
.selectAll('allPolylines')
.data(data_ready)
.enter()
.append('polyline')
.attr("stroke","black")
.style("fill","none")
.attr("stroke-width",1)
.attr('points',function(d) {
var posA = arc.centroid(d) // line insertion in the slice
var posB = outerArc.centroid(d) // line break: we use the other arc generator that has been built only for that
var posC = outerArc.centroid(d); // Label position = almost the same as posB
var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2 // we need the angle to see if the X position will be at the extreme right or extreme left
posC[0] = radius * 0.95 * (midangle < Math.PI ? 1 : -1); // multiply by 1 or -1 to put it on the right or on the left
return [posA,posC]
})
// Add the polylines between chart and labels:
svg
.selectAll('allLabels')
.data(data_ready)
.enter()
.append('text')
.text( function(d) { console.log(d.data.key) ; return d.data.value.facet } )
.attr('transform',function(d) {
var pos = outerArc.centroid(d);
var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
pos[0] = radius * 0.99 * (midangle < Math.PI ? 1 : -1);
return 'translate(' + pos + ')';
})
.style('text-anchor',function(d) {
var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
return (midangle < Math.PI ? 'start' : 'end')
})
})
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。