【问题标题】:Assign specific color to specific segment in D3 Pie Chart将特定颜色分配给 D3 饼图中的特定段
【发布时间】:2018-03-07 10:58:53
【问题描述】:

我使用 D3js (v4) 作为 Ember 组件构建了一个饼图/甜甜圈图,我正在尝试用特定颜色填充具有特定标签的段,但事实证明这很困难。

要为图表着色,我有以下代码:

marc = arc().outerRadius(radius - 10).innerRadius(radius - donutwidth),
color = scaleOrdinal().range(['#49b6d6', '#f59c1a', '#ff5b57',  '#00acac',]),

gEnter.append("path")
      .attr("d", marc)
      .attr("fill", (d, i) => {
        return color(i);
      })

以上工作正常,并用选定的颜色填充弧,但不是我想要的每个弧的颜色。数组的索引是一致的,所以我尝试简单地重新排列颜色的顺序,没有任何效果。

我还尝试使用基于索引的 if 语句,例如:

gEnter.append("path")
          .attr("d", marc)
          .attr("fill", (d, i) => {
            if (i === 0 { return color([0]) }
       })

这确实填充了索引为 0 的段,但没有从列表中选择颜色。更改 color([0]) 中的数字实际上根本不会产生任何变化。如果我尝试使用基于标签字符串而不是数组索引的条件,这也是正确的。

编辑

作为用于格式化图表数据的 Ember 计算属性的一部分,数据会重新排序,以便每个标签每次都以相同的顺序显示。计算的属性如下:

//takes the ember model 'referralsource' and groups it as needed   
sourceData: groupBy('referralsource', 'label'),

//ember computed property that provides data to chart
  pieData: Ember.computed('sourceData', function() {

    let objs = this.get('sourceData')
    let sortedObjs = _.sortBy(objs, 'value')
    let newArray = []

    sortedObjs.forEach(function(x) {
      let newLabel = x.value
      let count = x.items.length
      let newData = {
        label: newLabel,
        count: count
      }
      newArray.push(newData)
    })
    return newArray
  }),

【问题讨论】:

  • 您在创建甜甜圈时是否对任何内容进行排序或重新排序 - 如果您登录函数以选择填充,每个数据是否对应正确的索引?
  • 嗨安德鲁,我已经编辑了上面的问题。我确实对对象进行了排序,这是我尝试以一致的顺序列出它们的一部分 - 以前它们可以按我认为会导致每段颜色变化出现问题的任何顺序返回。当我记录 (i, d) 时,我可以看到 (i) 的值并不总是与单个对象中 index 的值匹配。事实上,唯一匹配的值是当我按照蒂亚戈关于添加 .domain 的建议时唯一着色的值

标签: javascript d3.js ember.js


【解决方案1】:

在您的第一个示例中,尝试更改:

color = scaleOrdinal().range(['#49b6d6', '#f59c1a', '#ff5b57',       '#00acac',]),

为此:

color = scaleOrdinal().range([0,4]),
color.domain(['#49b6d6', '#f59c1a', '#ff5b57', '#00acac']),

您用来指示比例尺大小的范围(在本例中为 4,因为您放置了 4 种颜色)并且域指定了该比例尺的每个位置的内容

【讨论】:

  • 我明白你在说什么。我将线更改为color = scaleOrdinal().range([0, 4]).domain(['#f59c1a','#49b6d6', '#ff5b57', '#00acac']),,这实际上停止了对弧的着色。他们仍然画画,但都是黑色的。我还需要改变什么吗?
  • 你把d3.scaleOrdinal...?还是只是 scaleOrdinal?
  • 它是一个 Ember 组件,因此 D3 作为模块导入,而不是通过 d3. 调用,感谢 ember-d3
【解决方案2】:

如果您的标签每次都相同(或从相同的选项池中提取),您可以指定一个特定的域。在序数范围内,域:

将域设置为指定的值数组。中的第一个元素 域将映射到范围中的第一个元素,第二个 域值到第二个范围值,依此类推 (from the API documentation)。

通过将域设置为包含每个可能的标签选项的数组,您可以轻松地为每个标签分配颜色。下面的示例有五个可能的标签,第一行使用与第二行相反的数据数组顺序,第三行使用带有重复项的随机顺序。所有三行始终将每个数据与特定颜色相关联:

var labels = ["redData","blueData","orangeData","pinkData","greenData"];

var colors = ["crimson","steelblue","orange","lightsalmon","lawngreen"];

var scale = d3.scaleOrdinal()
  .domain(labels)  // input values
  .range(colors);  // output values
  
var svg = d3.select("svg");

// initial order
svg.selectAll(null)
  .data(labels)
  .enter()
  .append("circle")
  .attr("cy",40)
  .attr("cx", function(d,i) { return i * 40+ 20; })
  .attr("r",15)
  .attr("fill",function(d) { return scale(d); });
  
// reverse order
svg.selectAll(null)
  .data(labels.reverse())
  .enter()
  .append("circle")
  .attr("cy",80)
  .attr("cx", function(d,i) { return i * 40+ 20; })
  .attr("r",15)
  .attr("fill",function(d) { return scale(d); });

// random labels
svg.selectAll(null)
  .data(["blueData","blueData","redData","orangeData","blueData"])
  .enter()
  .append("circle")
  .attr("cy",120)
  .attr("cx", function(d,i) { return i * 40+ 20; })
  .attr("r",15)
  .attr("fill",function(d) { return scale(d); });
  
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>


<svg width="600" height="400"></svg>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-27
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    相关资源
    最近更新 更多