Javascript D3.js创建动态颜色()函数

Javascript D3.js创建动态颜色()函数,javascript,d3.js,colors,pie-chart,Javascript,D3.js,Colors,Pie Chart,我正在D3.js中工作。 以下是数据: DATA.JSON [ { "key":"amministrazione", "categoria":"funzioni", "val2015":404571081, "val2013":374545999 }, { "key":"sociale", "categoria":"funzioni", "val2015":235251679, "val2013":258973653 }, { "key":"territorio e ambiente", "ca

我正在D3.js中工作。 以下是数据:

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
}
]
它显示了政府预算如何分配给不同的职能(即“关键”)。每年给出一个值(如“val2015”、“val2013”),每个函数都是宏观类别(如“funzioni”、“rimborso PRESTII”或“altro”)的一部分

我正在尝试创建一个color()函数,该函数根据以下情况动态更改其域和范围:

  • 任意指定为域的颜色范围:绿色表示“funzioni”,红色表示“rimborso prestiti”,蓝色表示“altro”
  • 每个类别中具有正值的功能(“键”)的数量,因此忽略给定年份内未分配资源的功能。通过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);
    }
    
    返回以下结果:

    这很接近,但是它为前12个楔子指定了一个红色范围(应该改为绿色范围),而没有为其他类别的楔子指定颜色

    选项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);}
            })
    
    麻烦的是,上面写的好像‘我’会为这三个类别分别统计。但它不会,它会为您选择的所有元素保留一个索引,一旦选择中的前12项完成,下一项将超出您描述的任何范围,并返回“#000000”-这就是为什么前12项是彩色的(前12个可能是红色的,因为您将红色范围指定给两个刻度,而绿色范围不使用),其余的则不使用

    作为一个快速解决方案,在数据本身中记录每个类别中出现的位置,如下所示:

    dataset.forEach (function (d) {if (d.categoria=="altro" && d.val2015>0) { countAltro += 1; d.catIndex = countAltro; }})
    
    var colorMap = {
        funzioni: colorFunzioni, 
        altro: colorAltro, 
        "rimborso prestiti": colorRimborso
    }
    
    对每个类别执行此操作

    然后在fill attr函数中执行以下操作:

    else if (d.data.categoria=="altro") {return colorAltro(d.data.catIndex);}
    
    同样,每个类别都需要这样做


    作为另一件事,您可以通过如下方式指定颜色来消除其他if:

    dataset.forEach (function (d) {if (d.categoria=="altro" && d.val2015>0) { countAltro += 1; d.catIndex = countAltro; }})
    
    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)
            })
    

    你是我的英雄!!非常感谢!!你们两个都解决了我数天来一直在绞尽脑汁的问题,并向我展示了一个非常有用的彩色地图方法。我知道它基本上是一个将键与值关联起来的字典,对吧?但是,我不明白accessor函数是如何使用它的。你能指出一些参考资料来了解更多信息吗?我觉得这在未来可能非常有用是的,它只是一个对象,使用categoria字段中的字符串作为键来指向颜色sclaes。因此,当您使用[d.data.categoria]访问它时,它应该从该对象中获取正确的颜色比例。我不理解的是
    if(scale)return scale(d.data.catIndex);
    。我添加了分号,对吗?…很抱歉,如果这似乎是一个微不足道的问题,但我想完全理解代码。
    if(比例)
    只需测试颜色刻度是否已返回-如果您的一个项目突然有一个新的类别名称,而该名称在颜色映射中没有条目,则该if语句将失败。如果它确实有刻度,则它仅使用其类别的项目索引值来调用它以返回颜色。