我正在构建一个星型可视化引擎,需要插值从API接收到的值。HSL色站是:
-.63, hsl: 228° 100% 80%,
.165, hsl: 224° 100% 90%,
.33, hsl: 240° 100% 98%,
.495, hsl: 64° 100% 92%,
.66, hsl: 52° 100% 82%,
.825, hsl: 28° 100% 66%,
2.057, hsl: 6° 95% 65%,每个恒星将返回一个颜色值之间的-.63和2.057,我需要一个函数,接受这个值,并得到一个颜色的光谱组成的上述停止。
我以前曾得到过一些帮助,但在我的一生中都找不到这一点,也没有找到一个简单的教程或HSL值插值的演练。唯一能解决这个问题的方法是通过一个外部库,但对于一些相对简单的东西来说,这似乎是一个荒谬的解决方案。任何帮助都将不胜感激!
发布于 2015-06-13 13:50:27
在HSB空间中一个简单的线性插值函数:
function get_color_for(value) {
var i, h,s,b,stops = [
[-0.63, [228, 100, 80]],
[0.165, [224, 100, 90]],
[0.33, [240, 100, 98]],
[0.495, [64, 100, 92]],
[0.66, [52, 100, 82]],
[0.825, [28, 100, 66]],
[2.057, [6, 95, 65]]
];
if (value <= stops[0][0]) return stops[0][1];
if (value >= stops[stops.length - 1][0]) return stops[stops.length - 1][1];
i = 0;
while (value > stops[i][0])
i++;
value -= stops[i-1][0];
value /= (stops[i][0]-stops[i-1][0]);
h = stops[i-1][1][0]+(stops[i][1][0]-stops[i-1][1][0])*value;
s = stops[i-1][1][1]+(stops[i][1][1]-stops[i-1][1][1])*value;
b = stops[i-1][1][2]+(stops[i][1][2]-stops[i-1][1][2])*value;
return [h,s,b];
}对于低于最小输入的值,它总是返回第一个颜色集,对于高于最大值的值,返回最后一个颜色集。
返回的值是一个HSL数组,可以立即在CSS中使用。如果您的环境需要RGB颜色,您可以使用hsl到rgb转换函数,例如在刚才这个问题中。检查您的输出设备对RGB范围的期望: 0.0到1.0、0到100或0到255。
请注意,此函数一般不能用于hsb。问题是hue部分:这个包在360度(度)左右,所以尝试在350和10之间插入将使它返回cyan (值约170),而不是红色(0的值)。
这是一个小提琴,显示一系列数字的输出。
发布于 2015-06-13 14:10:52
RGB内插效果更好,HSL在蓝色和黄色之间添加了绿色:

RGB插值:
function lerp(start, end, t) {
return (1 - t) * start + t * end;
}
function getColor(t) {
var colors = [
[153, 173, 255], [204, 218, 255], [245, 245, 255],
[252, 255, 214], [255, 243, 163], [255, 163, 82],
[251, 98, 81]
];
var domain = [-0.63, 0.165, 0.33, 0.495, 0.66, 0.825, 2.057];
if (t <= domain[0]) {
return colors[0];
}
if (t >= domain[domain.length - 1]) {
return colors[colors.length - 1];
}
for (var i = 0; t > domain[i]; i++);
var from = colors[i - 1];
var to = colors[i];
t = (t - domain[i - 1]) / (domain[i] - domain[i - 1]);
return [
lerp(from[0], to[0], t),
lerp(from[1], to[1], t),
lerp(from[2], to[2], t)
];
}绘制它:
function rgbToCSS(rgb) {
return 'rgb(' + Math.round(rgb[0]) + ',' +
Math.round(rgb[1]) + ',' +
Math.round(rgb[2]) + ')';
}
var canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 100;
var context = canvas.getContext('2d');
for (var i = 0; i < canvas.width; i++) {
context.fillStyle = rgbToCSS(getColor(lerp(-0.63, 2.057, i / canvas.width)));
context.fillRect(i, 0, 1, canvas.height);
}
document.body.appendChild(canvas);JSFiddle
https://stackoverflow.com/questions/30817921
复制相似问题