如何创建自定义色标?

时间:2019-03-20 21:24:19

标签: typescript d3.js

我正在尝试将一系列版本字符串映射为十六进制形式的RGB颜色系列。给定一组固定的版本字符串(例如services.AddMvc(opt => { opt.Filters.Add(new DecoderFallbackExceptionFilter()); }); )和几种颜色(["1.1.2", "1.1.3", ...]),我想创建一个比例尺,为每个版本字符串提供插值颜色。

我尝试过:

["#efebeb", "#4d4d4d", "#ff5d5d"]

但这只是三种颜色之间的交替:

ordinal scale just rotates through set colors.

我正在寻找平滑插值。当我尝试其他刻度尺时,打字稿抱怨类型错误,或者它们必须是数字,等等。我宁愿不预先计算颜色列表,因为我不知道需要多少颜色。

这可能吗?

1 个答案:

答案 0 :(得分:2)

因为您要插入一组固定的颜色,所以无论域长度有多大,我的解决方案都涉及使用线性刻度来创建颜色数组,然后将其传递给顺序刻度。 / p>

因此,您可以使用所需的3种颜色创建线性刻度...

const linearScale = d3.scaleLinear()
  .domain([0, 0.5, 1])
  .range(["#efebeb", "#4d4d4d", "#ff5d5d"]);

...,然后填充颜色数组,并将其传递给顺序刻度:

const colorArray = d3.range(data.length)
    .map(d => linearScale(d / (data.length - 1)));

const ordinalScale = d3.scaleOrdinal()
  .domain(data)
  .range(colorArray);

这种方法的优点是它是动态的,可以与域中任意数量的元素一起使用。

这里是一个只有3个元素(即您的情况下的三个版本)的演示:

const linearScale = d3.scaleLinear()
	.domain([0, 0.5, 1])
  .range(["#efebeb", "#4d4d4d", "#ff5d5d"]);
  
const data = "abc".split("");

const colorArray = d3.range(data.length).map(d=>linearScale(d/(data.length - 1)));

const ordinalScale = d3.scaleOrdinal()
	.domain(data)
  .range(colorArray);
  
const divs = d3.select("body")
	.selectAll(null)
  .data(data)
  .enter()
  .append("div")
  .style("background-color", d=>ordinalScale(d))
div {
  display: inline-block;
  width: 18px;
  height: 18px;
  margin-right: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

现在有10个版本:

const linearScale = d3.scaleLinear()
	.domain([0, 0.5, 1])
  .range(["#efebeb", "#4d4d4d", "#ff5d5d"]);
  
const data = "abcdefghij".split("");

const colorArray = d3.range(data.length).map(d=>linearScale(d/(data.length - 1)));

const ordinalScale = d3.scaleOrdinal()
	.domain(data)
  .range(colorArray);
  
const divs = d3.select("body")
	.selectAll(null)
  .data(data)
  .enter()
  .append("div")
  .style("background-color", d=>ordinalScale(d))
div {
  display: inline-block;
  width: 18px;
  height: 18px;
  margin-right: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

最后还有50个版本:

const linearScale = d3.scaleLinear()
	.domain([0, 0.5, 1])
  .range(["#efebeb", "#4d4d4d", "#ff5d5d"]);
  
const data = d3.range(50);

const colorArray = d3.range(data.length).map(d=>linearScale(d/(data.length - 1)));

const ordinalScale = d3.scaleOrdinal()
	.domain(data)
  .range(colorArray);
  
const divs = d3.select("body")
	.selectAll(null)
  .data(data)
  .enter()
  .append("div")
  .style("background-color", d=>ordinalScale(d))
div {
  display: inline-block;
  width: 18px;
  height: 18px;
  margin-right: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>