У меня есть значение, обозначающее +/-ность статьи, которое находится в диапазоне от -1 до 1, где -1 означает строго отрицательный результат, а 1 - строго положительный.
Я хочу превратить это в цвет так, чтобы он варьировался от красного (резко отрицательный) до серого (нейтральный) и заканчивался зеленым (сильно положительный).
Решение, которое я придумал, не полностью удовлетворяет тому, чего я пытаюсь достичь. Я не эксперт по цвету, но по какой-то причине любое значение, даже слегка отрицательное, например. -.07 дает ярко-красный цвет. Я также ожидаю, что любое положительное значение начнет выглядеть зеленым, но на самом деле я вижу оранжевый.
Что я делаю неправильно? Есть ли способ представить то, что мне нужно?
function getAsHslHeatMap(value: number) {
value = Math.max(-1, Math.min(1, value));
let hue;
if (value <= 0) {
// Transition from red to grey | Red is 0 degrees
hue = (1 - value) * 0;
} else {
// Transition from grey to green | Green is 120 degrees
hue = value * 120;
}
// Convert hue to an integer for CSS
hue = Math.round(hue);
let saturation = 100; // Full saturation
let lightness = 50; // Mid lightness
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
}
🤔 А знаете ли вы, что...
С помощью JavaScript можно валидировать данные на стороне клиента, что улучшает пользовательский опыт.
В вашем коде есть пара простых проблем:
0
всегда даст 0
(см.: hue = (1 - value) * 0;
)120
— зеленый. Следовательно, если value
меньше или равно 0
, вы хотите, чтобы hue
было 0
(красный), а если больше 0
- установите его на 120
(зеленый).red ... gray ... green
предполагает не только изменение hue
, но и насыщение. Если ваш value
находится в диапазоне -1.0
...0.0
...1.0
, это означает, что для определения saturation
, который будет передан в HSL, вам понадобится абсолютное (неотрицательное) число с плавающей запятой value
(умноженное на 100
, для процент)const getAsHslHeatMap = (value) => {
value = Math.max(-1, Math.min(1, value));
const hue = value > 0 ? 120 : 0; // 120 = green; 0 = red
const saturation = Math.abs(value) * 100;
return `hsl(${hue}, ${saturation}%, 50%)`;
};
// DEMO ONLY:
const elInput = document.querySelector("input");
const changeLikeness = () => document.body.style.backgroundColor = getAsHslHeatMap(elInput.valueAsNumber);
elInput.addEventListener("input", changeLikeness); // on input
changeLikeness(); // on init
Likeness: <input type=range min=-1 max=1 value=0 step=0.01>
Или визуально:
Negative...|...Positive
value: -1 ....... 0.0 ....... 1
hue: 0 0 120
saturation%: 100 ...... 0 ...... 100