我正在尝试将一系列版本字符串映射为十六进制形式的RGB颜色系列。给定一组固定的版本字符串(例如services.AddMvc(opt =>
{
opt.Filters.Add(new DecoderFallbackExceptionFilter());
});
)和几种颜色(["1.1.2", "1.1.3", ...]
),我想创建一个比例尺,为每个版本字符串提供插值颜色。
我尝试过:
["#efebeb", "#4d4d4d", "#ff5d5d"]
但这只是三种颜色之间的交替:
我正在寻找平滑插值。当我尝试其他刻度尺时,打字稿抱怨类型错误,或者它们必须是数字,等等。我宁愿不预先计算颜色列表,因为我不知道需要多少颜色。
这可能吗?
答案 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>