【问题标题】:How to create a custom color scale?如何创建自定义色标?
【发布时间】:2019-03-20 21:24:18
【问题描述】:

我正在尝试将一系列版本字符串以十六进制形式映射到一系列 RGB 颜色。给定一组固定的版本字符串(例如["1.1.2", "1.1.3", ...])和几种颜色(["#efebeb", "#4d4d4d", "#ff5d5d"]),我想创建一个刻度,为每个版本字符串提供一个插值颜色。

我试过了:

const palette = scaleOrdinal().domain(props.sdkVersions).range(["#efebeb", "#4d4d4d", "#ff5d5d"]);

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

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

这可能吗?

【问题讨论】:

  • 从这个问题中不清楚您的规模的域是什么。每个主要版本都有自己的颜色范围吗?您需要为每种颜色定义上限和下限。您能否提供这些输入的示例?
  • 对不起。版本字符串是任意的,可以是任何字符串(猫的类型、星期几等)。它们只是有序的,有 N 个,仅此而已。

标签: typescript d3.js


【解决方案1】:

因为您有一组要插值的固定颜色,所以无论域长度有多大,我的解决方案都涉及使用线性比例来创建颜色数组,您将把它传递给序数比例。

因此,您可以使用所需的 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>

【讨论】:

  • 谢谢,这正是我要找的原因。
猜你喜欢
  • 1970-01-01
  • 2021-09-27
  • 2021-06-15
  • 2018-12-30
  • 2011-02-10
  • 2012-01-24
  • 2013-01-22
  • 1970-01-01
  • 2016-03-07
相关资源
最近更新 更多