Как создать цветовую тепловую карту в JavaScript и CSS?

У меня есть значение, обозначающее +/-ность статьи, которое находится в диапазоне от -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}%)`;
}

Я не понимаю, как можно получить серый цвет, изменив только оттенок. Возможно, вам поможет статья, подобная этой: en.wikipedia.org/wiki/HSL_and_HSV

A Haworth 22.08.2024 23:54

Для отрицательных значений вам нужно сохранить оттенок красным (0) и изменить насыщенность до 0 (что дает серый цвет), а для положительных значений вам нужно сохранить оттенок 120 (зеленый) и насыщенность от 0 до 100. %.

A Haworth 23.08.2024 00:15

Примечательно, что если вместо этого использовать RGB, расчет сводится к выбору серого (x, x, x) (одинаковые числа для трех компонентов, чем выше, тем светлее). Отсюда вы можете отклониться на некоторое расстояние y от x, так что от красного->серого->зеленого будет x+y,x,x -> x,x,x -> x,x+y,x. (Вы также можете «уменьшить» два других с тем же эффектом, если хотите настроить яркость во время отображения). Хороший способ увидеть, что охватывает ваш диапазон, — это нарисовать цвета на одном участке от значений от -1 до 1.

Rogue 23.08.2024 15:17
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем коде есть пара простых проблем:

  • Умножение на 0 всегда даст 0 (см.: hue = (1 - value) * 0;)
  • Оттенок варьируется от 0 (красный) до 360 (красный), 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

Другие вопросы по теме