/**
* 计算两个 RGBA 颜色之间的欧几里得距离
* @param {number[]} color1 - 第一个颜色 [R, G, B, A]
* @param {number[]} color2 - 第二个颜色 [R, G, B, A]
* @returns {number} - 颜色距离
*/
function colorDistance(color1, color2) {
const [r1, g1, b1, a1] = color1;
const [r2, g2, b2, a2] = color2;
return Math.sqrt(Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2) + Math.pow(a1 - a2, 2));
}
/**
* 在色带中找到最接近的色值对应的数值
* @param {number[]} targetColor - 目标颜色 [R, G, B, A]
* @param {Array<[number, number[]]>} colorRamp - 色带,包含数值和对应的 RGBA 颜色
* @returns {number} - 最接近的数值
*/
function findValueFromColor(targetColor, colorRamp) {
let minDistance = Infinity;
let closestValue = 0;
// 遍历色带,找到最接近的颜色
for (const [value, color] of colorRamp) {
const distance = colorDistance(targetColor, color);
if (distance < minDistance) {
minDistance = distance;
closestValue = value;
}
}
return closestValue;
}
/**
* 在色带中通过插值找到目标色值对应的数值
* @param {number[]} targetColor - 目标颜色 [R, G, B, A]
* @param {Array<[number, number[]]>} colorRamp - 色带,包含数值和对应的 RGBA 颜色
* @returns {number} - 插值后的数值
*/
function findValueFromColorWithInterpolation(targetColor, colorRamp) {
let minDistance = Infinity;
let closestIndex = 0;
// 找到最接近的颜色索引
for (let i = 0; i < colorRamp.length; i++) {
const [, color] = colorRamp[i];
const distance = colorDistance(targetColor, color);
if (distance < minDistance) {
minDistance = distance;
closestIndex = i;
}
}
// 获取相邻的两个色值
const prevIndex = Math.max(closestIndex - 1, 0);
const nextIndex = Math.min(closestIndex + 1, colorRamp.length - 1);
const [prevValue, prevColor] = colorRamp[prevIndex];
const [nextValue, nextColor] = colorRamp[nextIndex];
// 计算目标色值在两个相邻色值之间的比例
const prevDistance = colorDistance(targetColor, prevColor);
const nextDistance = colorDistance(targetColor, nextColor);
const totalDistance = prevDistance + nextDistance;
// 插值计算数值
if (totalDistance === 0) {
return prevValue; // 如果距离为 0,直接返回前一个值
}
const t = nextDistance / totalDistance;
return prevValue + t * (nextValue - prevValue);
}
图例示例如下:
[
[0, [0, 0, 0, 0]],
[10.0, [1, 160, 246, 1]],
[10.5, [1, 164, 246, 1]],
[11.0, [1, 168, 245, 1]],
[11.5, [1, 172, 245, 1]],
[12.0, [1, 176, 244, 1]],
[12.5, [1, 180, 243, 1]],
[13.0, [1, 184, 243, 1]],
[13.5, [1, 188, 242, 1]],
[14.0, [1, 192, 242, 1]],
[14.5, [1, 196, 241, 1]],
[15.0, [0, 236, 236, 1]],
[15.5, [0, 232, 236, 1]],
[16.0, [0, 228, 236, 1]],
[16.5, [0, 224, 236, 1]],
[17.0, [0, 220, 236, 1]],
[17.5, [0, 216, 236, 1]],
[18.0, [0, 212, 236, 1]],
[18.5, [0, 208, 236, 1]],
[19.0, [0, 204, 236, 1]],
[19.5, [0, 200, 236, 1]],
[20.0, [0, 216, 0, 1]],
[20.5, [0, 212, 0, 1]],
[21.0, [0, 206, 0, 1]],
[21.5, [0, 202, 0, 1]],
[22.0, [0, 198, 0, 1]],
[22.5, [0, 194, 0, 1]],
[23.0, [0, 190, 0, 1]],
[23.5, [0, 186, 0, 1]],
[24.0, [0, 182, 0, 1]],
[24.5, [0, 178, 0, 1]],
[25.0, [1, 144, 0, 1]],
[25.5, [1, 140, 0, 1]],
[26.0, [1, 136, 0, 1]],
[26.5, [1, 132, 0, 1]],
[27.0, [1, 128, 0, 1]],
[27.5, [1, 124, 0, 1]],
[28.0, [1, 120, 0, 1]],
[28.5, [1, 116, 0, 1]],
[29.0, [1, 112, 0, 1]],
[29.5, [1, 108, 0, 1]],
[30.0, [255, 255, 0, 1]],
[30.5, [254, 253, 0, 1]],
[31.0, [253, 250, 0, 1]],
[31.5, [252, 247, 0, 1]],
[32.0, [251, 243, 0, 1]],
[32.5, [250, 240, 0, 1]],
[33.0, [249, 237, 0, 1]],
[33.5, [248, 233, 0, 1]],
[34.0, [247, 230, 0, 1]],
[34.5, [246, 227, 0, 1]],
[35.0, [231, 192, 0, 1]],
[35.5, [232, 188, 0, 1]],
[36.0, [233, 184, 0, 1]],
[36.5, [234, 180, 0, 1]],
[37.0, [235, 176, 0, 1]],
[37.5, [236, 172, 0, 1]],
[38.0, [237, 168, 0, 1]],
[38.5, [238, 164, 0, 1]],
[39.0, [239, 160, 0, 1]],
[39.5, [240, 156, 0, 1]],
[40.0, [255, 144, 0, 1]],
[40.5, [246, 140, 0, 1]],
[41.0, [247, 136, 0, 1]],
[41.5, [248, 132, 0, 1]],
[42.0, [249, 128, 0, 1]],
[42.5, [250, 124, 0, 1]],
[43.0, [251, 120, 0, 1]],
[43.5, [252, 116, 0, 1]],
[44.0, [253, 112, 0, 1]],
[44.5, [255, 108, 0, 1]],
[45.0, [255, 0, 0, 1]],
[45.5, [253, 0, 0, 1]],
[46.0, [251, 0, 0, 1]],
[46.5, [249, 0, 0, 1]],
[47.0, [247, 0, 0, 1]],
[47.5, [245, 0, 0, 1]],
[48.0, [243, 0, 0, 1]],
[48.5, [241, 0, 0, 1]],
[49.0, [239, 0, 0, 1]],
[49.5, [237, 0, 0, 1]],
[50.0, [214, 0, 0, 1]],
[50.5, [212, 0, 0, 1]],
[51.0, [210, 0, 0, 1]],
[51.5, [208, 0, 0, 1]],
[52.0, [206, 0, 0, 1]],
[52.5, [204, 0, 0, 1]],
[53.0, [202, 0, 0, 1]],
[53.5, [200, 0, 0, 1]],
[54.0, [198, 0, 0, 1]],
[54.5, [196, 0, 0, 1]],
[55.0, [192, 0, 0, 1]],
[55.5, [190, 0, 0, 1]],
[56.0, [188, 0, 0, 1]],
[56.5, [186, 0, 0, 1]],
[57.0, [184, 0, 0, 1]],
[57.5, [182, 0, 0, 1]],
[58.0, [180, 0, 0, 1]],
[58.5, [178, 0, 0, 1]],
[59.0, [176, 0, 0, 1]],
[59.5, [174, 0, 0, 1]],
[60.0, [255, 0, 240, 1]],
[60.5, [247, 0, 234, 1]],
[61.0, [239, 0, 228, 1]],
[61.5, [231, 0, 222, 1]],
[62.0, [223, 0, 216, 1]],
[62.5, [215, 0, 210, 1]],
[63.0, [207, 0, 204, 1]],
[63.5, [199, 0, 198, 1]],
[64.0, [191, 0, 192, 1]],
[64.5, [183, 0, 186, 1]],
[65.0, [150, 0, 180, 1]],
[65.5, [152, 15, 186, 1]],
[66.0, [154, 30, 192, 1]],
[66.5, [156, 45, 198, 1]],
[67.0, [158, 60, 204, 1]],
[67.5, [160, 75, 210, 1]],
[68.0, [162, 90, 216, 1]],
[68.5, [164, 105, 222, 1]],
[69.0, [167, 135, 228, 1]],
[69.5, [170, 140, 234, 1]],
[70.0, [173, 144, 240, 1]],
]
用法:
// 示例目标颜色
const targetColor = [1, 170, 245, 1]; // 某个颜色值
// 方法 1:直接找到最接近的数值
const closestValue = findValueFromColor(targetColor, colorRamp);
console.log('Closest value:', closestValue);
// 方法 2:通过插值找到更精确的数值
const interpolatedValue = findValueFromColorWithInterpolation(targetColor, colorRamp);
console.log('Interpolated value:', interpolatedValue);