动态颜色映射

时间:2019-07-17 07:22:29

标签: javascript d3.js svg

我正在使用d3根据称为type的属性对圆形填充进行颜色编码。它可能只有一种类型,或者最多可能有两种。我的数据是这样的:

var data = [{'company':'companyA','products':23,'aum':25997692757,'type':['Industry senior exe'],'date':'2015-02'},
{'company':'companyB','products':24,'aum':3548692757,'type':['Industry senior exe','Star'],'date':'2016-02'}
];

请注意,type属性是一个列表。

var colorMap = {
    'Industry senior exe':'blue',
    'Star':'Gray'
};

如果只有一个type,则圆圈的填充是微不足道的:

.style('fill', function(d) { return colorMap[d.type[0]})

然而,似乎有点高大的是如何处理列表长度较长的情况-d.type[1]。我的目标是:如果 type不止一个,则圆圈将是蓝色的一半和灰色的一半。听起来很简单,但确实让我感到难过。

问题

如何处理上面d3中所述的动态填充逻辑?

1 个答案:

答案 0 :(得分:3)

简而言之:您(在当前规范下)不能用一种以上的颜色填充<circle>之类的元素。因此,一种可能的解决方案是使用SVG <linearGradient>

该方法的缺点是,假设您有多个具有不同颜色选择的不同圆,给出了大量组合,则需要创建相同数量的线性渐变。

例如,在输入选择后使用each

var gradient = svg.append("defs")
    .append("linearGradient")
    .attr("id", "gradient" + i)
    .attr("x1", "0%")
    .attr("x2", "100%")
  gradient.append("stop")
    .attr("offset", "50%")
    .attr("stop-color", colorMap[d.type[0]])
  gradient.append("stop")
    .attr("offset", "50%")
    .attr("stop-color", d.type.length === 2 ? colorMap[d.type[1]] : colorMap[d.type[0]]);

以下是使用您的数据的演示:

var data = [{
    'company': 'companyA',
    'products': 23,
    'aum': 25997692757,
    'type': ['Industry senior exe'],
    'date': '2015-02'
  },
  {
    'company': 'companyB',
    'products': 24,
    'aum': 3548692757,
    'type': ['Industry senior exe', 'Star'],
    'date': '2016-02'
  }
];
var colorMap = {
  'Industry senior exe': 'blue',
  'Star': 'gray'
};
var svg = d3.select("svg");
var circles = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", 50)
  .attr("cx", (_, i) => 50 + i * 100)
  .attr("r", 40);
circles.each(function(d, i) {
  var gradient = svg.append("defs")
    .append("linearGradient")
    .attr("id", "gradient" + i)
    .attr("x1", "0%")
    .attr("x2", "100%")
  gradient.append("stop")
    .attr("offset", "50%")
    .attr("stop-color", colorMap[d.type[0]])
  gradient.append("stop")
    .attr("offset", "50%")
    .attr("stop-color", d.type.length === 2 ? colorMap[d.type[1]] : colorMap[d.type[0]]);
  d3.select(this)
    .attr("fill", "url(#gradient" + i + ")")
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

另一方面,如果只有两种组合(全是蓝色和蓝灰色),则只需要两个线性渐变。