javascript - 动态颜色映射

标签 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'
};

如果只有一种类型,那么圆的填充就很简单:

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

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

问题

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

最佳答案

简单地说:(在当前规范下)您不能填充像 <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>

另一方面,如果您只有两种组合 - 全部为蓝色和蓝灰色 - 您将只需要两个线性渐变。

关于javascript - 动态颜色映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57070557/

相关文章:

javascript - 我需要帮助使用 Ajax、PHP 和 mySQL 将信息发送到我的服务器而不使用表单

javascript - 四舍五入到特定数字

css - 内联 SVG 在 IE 中不能用作背景图像

javascript - 从 Javascript 访问 SVG 对象时收到 Uncaught SecurityError

css - 反转CSS关键帧动画

javascript - 数组练习javascript的同时循环

javascript - 另一个 CoffeeScript 错误

javascript - Sunburst D3 文本问题

javascript - D3 v4:具有嵌套g标签的任意复杂数组的元素之间的间距和绑定(bind)

javascript - 将元素悬停在图表上