D3.js -使图例使用描述性字符串的图例而不是数据值



可以从图片(https://i.stack.imgur.com/TtIP7.jpg)中看到,我已经很好地设置了我的饼/甜甜圈图。但是,我如何使图例使用JSON文件(name)中包含的描述性字符串而不是数据值(total)?谢谢!

const project = d3.select(".project")
const svg = project.append("svg").attr("width",700).attr("height",600)
const margin = {top:20,right:20,bottom:70,left:70}
const graphWidth = 600-margin.left - margin.right
const graphHeight = 600 - margin.top - margin.bottom
const arcPath = d3.arc().outerRadius(190).innerRadius(70)
const legendRectSize = 18;                                  // NEW
const legendSpacing = 4;  
// title
svg.append("text").attr("class","title").attr("dy","10%").attr("dx","10%").text("Impact of COVID-19 on Business")
.attr("fill", "black")
// choose colour scheme
const colourScale = d3.scaleOrdinal(d3["schemeDark2"])
// set up a canvas and the pie chart
const pieCanvas = svg.append("g").attr("width",graphWidth/2).attr("height",graphWidth/2)
.attr("transform", `translate(${margin.left + 200},${margin.top + 250})`)
const pie = d3.pie().sort(null).value(data=>data.total)
// get data from CSV
function getData() {
d3.json("./data/piedata1.json", function(d) {return d}).then(drawPie)
}
getData()
//draw the pie chart
function drawPie(data) {
colourScale.domain(data.map(d=>d.total))
const angles = pie(data)
const paths = pieCanvas.selectAll("path").data(angles)
paths.enter().append("path").attr("d", arcPath).attr("class","arc")
.attr("stroke","white").attr("fill", d=>colourScale(d.data.total))
//add legend
const legend = svg.selectAll('.legend').data(colourScale.domain()).enter().append('g')                                          
.attr('class', 'legend').attr('transform', function(d, i) {                    
const height = legendRectSize + legendSpacing          
const offset =  height * colourScale.domain().length / 2   
const horz = 30 * legendRectSize                       
const vert = i * height - offset + 200                      
return 'translate(' + horz + ',' + vert + ')'});  
legend.append('rect').attr('width', legendRectSize).attr('height', legendRectSize)                        
.style('fill', colourScale).style('stroke', colourScale)                      

legend.append('text').attr('x', legendRectSize + legendSpacing)           
.attr('y', legendRectSize - legendSpacing).text(function(d) { return d })                      
}

JSON文件在这里

[
{"name": "critical impact","total": 100,"Percent":1.39},
{"name": "significant impact","total": 1500,"Percent":20.83},
{"name": "limited impact","total": 4100,"Percent":56.94},
{"name": "no impact","total": 400,"Percent":5.56},
{"name": "positive impact","total": 1100,"Percent":15.28}
]

当前创建的色阶域由总数组成。你可能不应该这样做:有些总数可能是相等的,但如果它们代表不同的东西,你可能不希望它们的颜色相同。

colourScale.domain(data.map(d=>d.name))代替:colourScale.domain(data.map(d=>d.total))

这意味着你还需要传递正确的参数尺度以及当着色楔形:.attr("stroke","white").attr("fill", d=>colourScale(d.data.name))

下面是一个例子:

var data = [
{"name": "critical impact","total": 100,"Percent":1.39},
{"name": "significant impact","total": 1500,"Percent":20.83},
{"name": "limited impact","total": 4100,"Percent":56.94},
{"name": "no impact","total": 400,"Percent":5.56},
{"name": "positive impact","total": 1100,"Percent":15.28}
]
const project = d3.select(".project")
const svg = project.append("svg").attr("width",700).attr("height",600)
const margin = {top:20,right:20,bottom:70,left:70}
const graphWidth = 600-margin.left - margin.right
const graphHeight = 600 - margin.top - margin.bottom
const arcPath = d3.arc().outerRadius(190).innerRadius(70)
const legendRectSize = 18;                                  // NEW
const legendSpacing = 4;  
// title
svg.append("text").attr("class","title").attr("dy","10%").attr("dx","10%").text("Impact of COVID-19 on Business")
.attr("fill", "black")
// choose colour scheme
const colourScale = d3.scaleOrdinal(d3["schemeDark2"])
// set up a canvas and the pie chart
const pieCanvas = svg.append("g").attr("width",graphWidth/2).attr("height",graphWidth/2)
.attr("transform", `translate(${margin.left + 200},${margin.top + 250})`)
const pie = d3.pie().sort(null).value(data=>data.total)
// get data from CSV
drawPie(data);

//draw the pie chart
function drawPie(data) {
colourScale.domain(data.map(d=>d.name))
const angles = pie(data)
const paths = pieCanvas.selectAll("path").data(angles)
paths.enter().append("path").attr("d", arcPath).attr("class","arc")
.attr("stroke","white").attr("fill", d=>colourScale(d.data.name))
//add legend
const legend = svg.selectAll('.legend').data(colourScale.domain()).enter().append('g')                                          
.attr('class', 'legend').attr('transform', function(d, i) {                    
const height = legendRectSize + legendSpacing          
const offset =  height * colourScale.domain().length / 2   
const horz = 30 * legendRectSize                       
const vert = i * height - offset + 200                      
return 'translate(' + horz + ',' + vert + ')'});  
legend.append('rect').attr('width', legendRectSize).attr('height', legendRectSize)                        
.style('fill', colourScale).style('stroke', colourScale)                      

legend.append('text').attr('x', legendRectSize + legendSpacing)           
.attr('y', legendRectSize - legendSpacing).text(function(d) { return d })                      
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="project"></div>

假设你想同时访问total和name,那么我们可以在创建图例时使用整个数据集,并简单地将正确的属性传递给比例和附加文本(而不是传递颜色比例域时的整个数据):

var data = [
{"name": "critical impact","total": 100,"Percent":1.39},
{"name": "significant impact","total": 1500,"Percent":20.83},
{"name": "limited impact","total": 4100,"Percent":56.94},
{"name": "no impact","total": 400,"Percent":5.56},
{"name": "positive impact","total": 1100,"Percent":15.28}
]
const project = d3.select(".project")
const svg = project.append("svg").attr("width",700).attr("height",600)
const margin = {top:20,right:20,bottom:70,left:70}
const graphWidth = 600-margin.left - margin.right
const graphHeight = 600 - margin.top - margin.bottom
const arcPath = d3.arc().outerRadius(190).innerRadius(70)
const legendRectSize = 18;                                  // NEW
const legendSpacing = 4;  
// title
svg.append("text").attr("class","title").attr("dy","10%").attr("dx","10%").text("Impact of COVID-19 on Business")
.attr("fill", "black")
// choose colour scheme
const colourScale = d3.scaleOrdinal(d3["schemeDark2"])
// set up a canvas and the pie chart
const pieCanvas = svg.append("g").attr("width",graphWidth/2).attr("height",graphWidth/2)
.attr("transform", `translate(${margin.left + 200},${margin.top + 250})`)
const pie = d3.pie().sort(null).value(data=>data.total)
// get data from CSV
drawPie(data);

//draw the pie chart
function drawPie(data) {
colourScale.domain(data.map(d=>d.name))
const angles = pie(data)
const paths = pieCanvas.selectAll("path").data(angles)
paths.enter().append("path").attr("d", arcPath).attr("class","arc")
.attr("stroke","white").attr("fill", d=>colourScale(d.data.name))
//add legend
const legend = svg.selectAll('.legend').data(data).enter().append('g')                                          
.attr('class', 'legend').attr('transform', function(d, i) {                    
const height = legendRectSize + legendSpacing          
const offset =  height * colourScale.domain().length / 2   
const horz = 30 * legendRectSize                       
const vert = i * height - offset + 200                      
return 'translate(' + horz + ',' + vert + ')'});  
legend.append('rect').attr('width', legendRectSize).attr('height', legendRectSize)                        
.style('fill', d=>colourScale(d.name)).style('stroke', d=>colourScale(d.name))                      

legend.append('text').attr('x', legendRectSize + legendSpacing)           
.attr('y', legendRectSize - legendSpacing).text(function(d) { return d.name + "(" + d.total + ")"; })                      
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="project"></div>

最新更新