DC图表中的动态颜色

时间:2019-01-06 18:09:19

标签: dc.js

我正在使用DC.js构建数据仪表板,想知道是否有可能根据其所引用字段中的值动态更改饼图中的切片颜色。

基本上,我已经建立了一个饼图,汇总了不同超级英雄的服装颜色,并且我希望能够使用它所指的颜色为每个切片着色-因此,“黑色”的切片被涂成黑色, “绿色”的切片被涂成绿色,依此类推。

我对DC.js还是很陌生,所以接受它可能是不可能的,但是想把它扔在那里,看看是否可以做到!

我尝试在.ordinalColors中包含一个数组,但无法确定是否有一种方法可以动态地从字段中提取数据。我假设我必须将.csv文件中的数据更改为可以识别为颜色参考的字符串,但不确定如何执行此操作。

function show_costume_color(ndx) {
   var costume_color_dim = ndx.dimension(dc.pluck('Costume Colour'));
   var costume_color = costume_color_dim.group();

dc.pieChart('#costume-color')
    .width(500)
    .height(500)
    .radius(500)
    .innerRadius(100)
    .slicesCap([7])
    .transitionDuration(1500)
    .dimension(costume_color_dim)
    .group(costume_color);
}

CSV数据采用以下格式

ID,name,Gender,Eye color,Race,Hair color,Publisher,Alignment,Superpower,Superpower Strength Level,Costume 
Colour
0,A-Bomb,Male,Yellow,Human,No Hair,Marvel Comics,Good,Superhuman 
Strength,10,None
1,Abin Sur,Male,Blue,Ungaran,No Hair,DC Comics,Good,Cosmic Power,40,Green

2 个答案:

答案 0 :(得分:0)

是的,当然。一切都在dc.js中动态指定。

假设您正在使用dc.js v3(和d3 v4 +),我建议这样做的方法是通过创建另一个具有所需颜色分配的CSV文件,例如

Name, RGB
Red, #ff1122
Blue, #1133ff
...

然后,您可以使用Promise.all()与数据并行加载第二个文件,

Promise.all([d3.csv('data.csv'), d3.csv('colors.csv')])
    .then(function(data, colors) {
  // rest of code will go here
});

ordinalColors是一种很好的便捷方法,但是如果您希望完全控制并准确了解正在发生的情况,最好提供自己的色标。在这种情况下,我们需要一个有序刻度,它将特定的离散值映射到特定的颜色。

在幕后,dc.js始终通过使用colorAccessor来获取商品的值,然后使用色标来映射该值来处理颜色。您可以将访问器返回的值视为“颜色名称”,这非常方便,因为这正是您想要的。

因此,您可以使用颜色名称的域和RGB颜色范围填充d3.scaleOrdinal

var colorScale = d3.scaleOrdinal()
    .domain(colors.map(row => row.Name))
    .range(colors.map(row => row.RGB));

现在使用.colors()将其提供给图表:

chart.colors(colorScale);

此方法真正方便的是,您可以为多个图表提供相同的色标,以确保它们是一致的。在dc.js中,这是您不会自动获得的,因为图表彼此之间的了解并不多。

答案 1 :(得分:0)

因此,我设法通过大量的反复试验弄清楚了这一点,现在我离开了仪表板。戈登,感谢您的帮助-确实发挥了作用!它需要整理一下,但是我的工作测试代码如下。

// Bring in data from both csv files

Promise.all([d3.csv("../data/heroes_information.csv"), 
d3.csv("../data/costume_colors.csv")])
    .then(function(data) {

        // Tidy up data before use

        data.forEach(function(d) {
            d.Height = +d.Height;
            d.Weight = +d.Weight;
            d.Strength = +d.Strength;
        });

        // Bring in colorScale to dynamically color pie chart slices

        var ndxcol = crossfilter(data[1]);

        var colorScale = d3.scaleOrdinal()
            .domain(data[1].map(row => row.Name))
            .range(data[1].map(row => row.RGB));

        // Bring in superhero data

        var ndx = crossfilter(data[0]);

        // Define chart types

        var publisherSelector = dc.selectMenu('#publisher-selector')
        var genderChart = dc.rowChart('#gender-balance');

        // Define chart dimensions

        var publisherChoice = ndx.dimension(dc.pluck('Publisher'));
        var genderBalance = ndx.dimension(dc.pluck('Gender'));

        // Define chart groups

        var genderNumber = genderBalance.group();
        var publisherNumber = publisherChoice.group();

        // Draw charts

        publisherSelector
            .dimension(publisherChoice)
            .group(publisherNumber);

        genderChart
            .width(500)
            .height(200)
            .margins({ top: 30, right: 30, bottom: 30, left: 30 })
            .dimension(genderBalance)
            .group(genderNumber)
            .gap(6)
            .colors(colorScale)
            .transitionDuration(500)
            .x(d3.scaleOrdinal())
            .elasticX(true);

        dc.renderAll();

    });