D3.js 创建动态 color() 函数
D3.js create a dynamic color() function
我正在 D3.js 中处理 this pie-chart。
这是数据:
DATA.JSON
[
{
"key":"amministrazione",
"categoria":"funzioni",
"val2015":404571081,
"val2013":374545999
},
{
"key":"sociale",
"categoria":"funzioni",
"val2015":235251679,
"val2013":258973653
},
{
"key":"territorio e ambiente",
"categoria":"funzioni",
"val2015":286164667,
"val2013":274949400
},
{
"key":"viabilità e trasporti",
"categoria":"funzioni",
"val2015":144185664,
"val2013":140619534
},
{
"key":"istruzione",
"categoria":"funzioni",
"val2015":168774925,
"val2013":170016208
},
{
"key":"cultura",
"categoria":"funzioni",
"val2015":55868045,
"val2013":55735535
},
{
"key":"sport",
"categoria":"funzioni",
"val2015":27219432,
"val2013":31244800
},
{
"key":"turismo",
"categoria":"funzioni",
"val2015":9544845,
"val2013":7674419
},
{
"key":"sviluppo economico",
"categoria":"funzioni",
"val2015":14790363,
"val2013":16635868
},
{
"key":"servizi produttivi",
"categoria":"funzioni",
"val2015":4334,
"val2013":4440
},
{
"key":"polizia locale",
"categoria":"funzioni",
"val2015":99007202,
"val2013":102065987
},
{
"key":"giustizia",
"categoria":"funzioni",
"val2015":12147068,
"val2013":12880138
},
{
"key":"anticipazioni di cassa",
"categoria":"rimborso prestiti",
"val2015":304323808,
"val2013":304323808
},
{
"key":"finanziamenti a breve termine",
"categoria":"rimborso prestiti",
"val2015":0,
"val2013":0
},
{
"key":"prestiti obbligazionari",
"categoria":"rimborso prestiti",
"val2015":38842996,
"val2013":36652213
},
{
"key":"quota capitale di debiti pluriennali",
"categoria":"rimborso prestiti",
"val2015":0,
"val2013":47152
},
{
"key":"quota capitale di mutui e prestiti",
"categoria":"rimborso prestiti",
"val2015":128508755,
"val2013":329885961
},
{
"key":"spese per conto terzi",
"categoria":"altro",
"val2015":232661261,
"val2013":236921438
},
{
"key":"disavanzo di amministrazione",
"categoria":"altro",
"val2015":0,
"val2013":0
}
]
它显示了政府预算如何分配给不同的职能(即 "key")。每年都有一个值(例如 "val2015"、"val2013"),每个函数都是宏类别的一部分(即 "funzioni"、"rimborso prestiti" 或 "altro").
我正在尝试创建一个 color() 函数,它根据以下条件动态更改其域和范围:
- 任意指定为域的颜色范围:"funzioni" 的 greenRange,"rimborso prestiti" 的 redRange 和 "altro"
的 blueRange
- 每个类别中具有正值的功能("key")的数量,因此忽略了在给定年份没有分配资源的功能。通过 count() 函数完成(有效)
- 然后根据点 2 的 count() 函数为每个范围创建 X 数量的阴影
- 并为饼图的每个楔形分配适当的颜色
这是我的起点:
var greenRange = ["rgb(199,233,192)", "rgb(0,68,27)"]; //range for the first 12 wedges of the pie (assuming they are all >0)
var redRange = ["rgb(252,187,161)", "rgb(103,0,13)"]; //range for the following 5 wedges of the pie (same assumption)
var blueRange = ["rgb(198,219,239)", "rgb(8,48,107)"]; //range for the last 3 wedges of the pie (same assumption)
我尝试了两个选项,但都不起作用。
选项 1
function draw () {
//(1) count the number of data points with value > 0 in each category - This works well!
var countFunzioni=0;
dataset.forEach (function (d) {if (d.categoria=="funzioni" && d.val2015>0) { countFunzioni += 1;}})
var countRimborso=0;
dataset.forEach (function (d) {if (d.categoria=="rimborso prestiti" && d.val2015>0) { countRimborso += 1;}})
var countAltro=0;
dataset.forEach (function (d) {if (d.categoria=="altro" && d.val2015>0) { countAltro += 1;}})
//(2) create a color method for each category based on a the count calculated above and the range I determined
var colorFunzioni = d3.scale.linear()
.domain([0, countFunzioni])
.range(redRange);
var colorRimborso = d3.scale.linear()
.domain([0, countRimborso])
.range(redRange);
var colorAltro = d3.scale.linear()
.domain([0, countAltro])
.range(blueRange);
//draw the chart
chart = d3.select("#visualizationInner")
.append("svg")
.attr("id", "visualization")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
//draw and color the paths
var path = chart.datum(dataset).selectAll("path")
.data(pie)
.enter()
.append("path")
//(3) return the appropriate color method depending on the datum's category
.attr("fill", function(d, i) {
if (d.data.categoria=="funzioni") {return colorFunzioni(i);}
else if (d.data.categoria=="rimborso prestiti") {return colorRimborso(i);}
else if (d.data.categoria=="altro") {return colorAltro(i);}
})
.style("fill-opacity", 0.75)
.attr("d", arc);
}
哪个returns这个结果:
这很接近,但是它为前 12 个楔形分配了一系列红色(应该改为 greenRange),而没有为属于其他类别的楔形分配颜色
选项 2
function draw () {
//(1) same as above
//(2) create a color method that adapts to each category's count and range
var color = d3.scale.linear()
.domain([0, function (d) {
if (d.data.categoria=="funzioni") {return countFunzioni;}
else if (d.data.categoria=="rimborso prestiti") {return countRimborso;}
else if (d.data.categoria=="altro") {return countAltro;}
}])
.range(function (d) {
if (d.cdata.ategoria=="funzioni") {return greenRange;}
else if (d.data.categoria=="rimborso prestiti") {return redRange;}
else if (d.data.categoria=="altro") {return blueRange;}
});
////(3) return the appropriate color method depending on the datum's category
.attr("fill", function(d, i) {return color(i);}
}
这没有完成任何着色。
知道如何解决这个问题吗?
选项1备注:
.attr("fill", function(d, i) {
if (d.data.categoria=="funzioni") {return colorFunzioni(i);}
else if (d.data.categoria=="rimborso prestiti") {return colorRimborso(i);}
else if (d.data.categoria=="altro") {return colorAltro(i);}
})
问题是上面写的好像 'i' 会为这三个类别保持单独的计数。不过,它不会为您选择的所有元素保留一个索引,一旦完成选择中的前 12 个项目,接下来的项目将超出您描述的任何比例范围 return "#000000" - 这就是为什么前 12 个是彩色的(前 12 个可能是红色的,因为您将红色范围分配给了两个刻度,并且未使用绿色范围)而其余的则没有.
作为快速修复,在数据本身中记录它在每个类别中出现的位置,如下所示:
dataset.forEach (function (d) {if (d.categoria=="altro" && d.val2015>0) { countAltro += 1; d.catIndex = countAltro; }})
对每个类别执行此操作
然后在填充属性函数中执行:
else if (d.data.categoria=="altro") {return colorAltro(d.data.catIndex);}
每个类别都需要完成。
作为一个单独的东西,你可以通过像这样分配颜色来摆脱那些 else-if:
var colorMap = {
funzioni: colorFunzioni,
altro: colorAltro,
"rimborso prestiti": colorRimborso
}
然后再做
.attr("fill", function(d, i) {
var scale = colorMap[d.data.categoria];
if (scale) return scale(d.data.catIndex)
})
我正在 D3.js 中处理 this pie-chart。 这是数据:
DATA.JSON
[
{
"key":"amministrazione",
"categoria":"funzioni",
"val2015":404571081,
"val2013":374545999
},
{
"key":"sociale",
"categoria":"funzioni",
"val2015":235251679,
"val2013":258973653
},
{
"key":"territorio e ambiente",
"categoria":"funzioni",
"val2015":286164667,
"val2013":274949400
},
{
"key":"viabilità e trasporti",
"categoria":"funzioni",
"val2015":144185664,
"val2013":140619534
},
{
"key":"istruzione",
"categoria":"funzioni",
"val2015":168774925,
"val2013":170016208
},
{
"key":"cultura",
"categoria":"funzioni",
"val2015":55868045,
"val2013":55735535
},
{
"key":"sport",
"categoria":"funzioni",
"val2015":27219432,
"val2013":31244800
},
{
"key":"turismo",
"categoria":"funzioni",
"val2015":9544845,
"val2013":7674419
},
{
"key":"sviluppo economico",
"categoria":"funzioni",
"val2015":14790363,
"val2013":16635868
},
{
"key":"servizi produttivi",
"categoria":"funzioni",
"val2015":4334,
"val2013":4440
},
{
"key":"polizia locale",
"categoria":"funzioni",
"val2015":99007202,
"val2013":102065987
},
{
"key":"giustizia",
"categoria":"funzioni",
"val2015":12147068,
"val2013":12880138
},
{
"key":"anticipazioni di cassa",
"categoria":"rimborso prestiti",
"val2015":304323808,
"val2013":304323808
},
{
"key":"finanziamenti a breve termine",
"categoria":"rimborso prestiti",
"val2015":0,
"val2013":0
},
{
"key":"prestiti obbligazionari",
"categoria":"rimborso prestiti",
"val2015":38842996,
"val2013":36652213
},
{
"key":"quota capitale di debiti pluriennali",
"categoria":"rimborso prestiti",
"val2015":0,
"val2013":47152
},
{
"key":"quota capitale di mutui e prestiti",
"categoria":"rimborso prestiti",
"val2015":128508755,
"val2013":329885961
},
{
"key":"spese per conto terzi",
"categoria":"altro",
"val2015":232661261,
"val2013":236921438
},
{
"key":"disavanzo di amministrazione",
"categoria":"altro",
"val2015":0,
"val2013":0
}
]
它显示了政府预算如何分配给不同的职能(即 "key")。每年都有一个值(例如 "val2015"、"val2013"),每个函数都是宏类别的一部分(即 "funzioni"、"rimborso prestiti" 或 "altro").
我正在尝试创建一个 color() 函数,它根据以下条件动态更改其域和范围:
- 任意指定为域的颜色范围:"funzioni" 的 greenRange,"rimborso prestiti" 的 redRange 和 "altro" 的 blueRange
- 每个类别中具有正值的功能("key")的数量,因此忽略了在给定年份没有分配资源的功能。通过 count() 函数完成(有效)
- 然后根据点 2 的 count() 函数为每个范围创建 X 数量的阴影
- 并为饼图的每个楔形分配适当的颜色
这是我的起点:
var greenRange = ["rgb(199,233,192)", "rgb(0,68,27)"]; //range for the first 12 wedges of the pie (assuming they are all >0)
var redRange = ["rgb(252,187,161)", "rgb(103,0,13)"]; //range for the following 5 wedges of the pie (same assumption)
var blueRange = ["rgb(198,219,239)", "rgb(8,48,107)"]; //range for the last 3 wedges of the pie (same assumption)
我尝试了两个选项,但都不起作用。
选项 1
function draw () {
//(1) count the number of data points with value > 0 in each category - This works well!
var countFunzioni=0;
dataset.forEach (function (d) {if (d.categoria=="funzioni" && d.val2015>0) { countFunzioni += 1;}})
var countRimborso=0;
dataset.forEach (function (d) {if (d.categoria=="rimborso prestiti" && d.val2015>0) { countRimborso += 1;}})
var countAltro=0;
dataset.forEach (function (d) {if (d.categoria=="altro" && d.val2015>0) { countAltro += 1;}})
//(2) create a color method for each category based on a the count calculated above and the range I determined
var colorFunzioni = d3.scale.linear()
.domain([0, countFunzioni])
.range(redRange);
var colorRimborso = d3.scale.linear()
.domain([0, countRimborso])
.range(redRange);
var colorAltro = d3.scale.linear()
.domain([0, countAltro])
.range(blueRange);
//draw the chart
chart = d3.select("#visualizationInner")
.append("svg")
.attr("id", "visualization")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
//draw and color the paths
var path = chart.datum(dataset).selectAll("path")
.data(pie)
.enter()
.append("path")
//(3) return the appropriate color method depending on the datum's category
.attr("fill", function(d, i) {
if (d.data.categoria=="funzioni") {return colorFunzioni(i);}
else if (d.data.categoria=="rimborso prestiti") {return colorRimborso(i);}
else if (d.data.categoria=="altro") {return colorAltro(i);}
})
.style("fill-opacity", 0.75)
.attr("d", arc);
}
哪个returns这个结果:
这很接近,但是它为前 12 个楔形分配了一系列红色(应该改为 greenRange),而没有为属于其他类别的楔形分配颜色
选项 2
function draw () {
//(1) same as above
//(2) create a color method that adapts to each category's count and range
var color = d3.scale.linear()
.domain([0, function (d) {
if (d.data.categoria=="funzioni") {return countFunzioni;}
else if (d.data.categoria=="rimborso prestiti") {return countRimborso;}
else if (d.data.categoria=="altro") {return countAltro;}
}])
.range(function (d) {
if (d.cdata.ategoria=="funzioni") {return greenRange;}
else if (d.data.categoria=="rimborso prestiti") {return redRange;}
else if (d.data.categoria=="altro") {return blueRange;}
});
////(3) return the appropriate color method depending on the datum's category
.attr("fill", function(d, i) {return color(i);}
}
这没有完成任何着色。
知道如何解决这个问题吗?
选项1备注:
.attr("fill", function(d, i) {
if (d.data.categoria=="funzioni") {return colorFunzioni(i);}
else if (d.data.categoria=="rimborso prestiti") {return colorRimborso(i);}
else if (d.data.categoria=="altro") {return colorAltro(i);}
})
问题是上面写的好像 'i' 会为这三个类别保持单独的计数。不过,它不会为您选择的所有元素保留一个索引,一旦完成选择中的前 12 个项目,接下来的项目将超出您描述的任何比例范围 return "#000000" - 这就是为什么前 12 个是彩色的(前 12 个可能是红色的,因为您将红色范围分配给了两个刻度,并且未使用绿色范围)而其余的则没有.
作为快速修复,在数据本身中记录它在每个类别中出现的位置,如下所示:
dataset.forEach (function (d) {if (d.categoria=="altro" && d.val2015>0) { countAltro += 1; d.catIndex = countAltro; }})
对每个类别执行此操作
然后在填充属性函数中执行:
else if (d.data.categoria=="altro") {return colorAltro(d.data.catIndex);}
每个类别都需要完成。
作为一个单独的东西,你可以通过像这样分配颜色来摆脱那些 else-if:
var colorMap = {
funzioni: colorFunzioni,
altro: colorAltro,
"rimborso prestiti": colorRimborso
}
然后再做
.attr("fill", function(d, i) {
var scale = colorMap[d.data.categoria];
if (scale) return scale(d.data.catIndex)
})