Как я могу генерировать цвета (не случайно), чтобы они имели другой цвет, а не оттенок? - PullRequest
2 голосов
/ 27 мая 2020

Возможно ли «добавить» другой цвет и, по сути, продолжить его с того места, где он остановился? Например, вы начинаете раскрашивать 30 элементов, но пользователь добавляет 31-й элемент. Есть ли способ продолжить работу с текущим сгенерированным набором и просто создать 31-й цвет, который соответствует предыдущим оттенкам и шагам? Я нашел пример, но не понимаю, как его можно использовать

function rainbow(numOfSteps, step) {
    // This function generates vibrant, "evenly spaced" colours (i.e. no clustering). This is ideal for creating easily distinguishable vibrant markers in Google Maps and other apps.
    // Adam Cole, 2011-Sept-14
    // HSV to RBG adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
    var r, g, b;
    var h = step / numOfSteps;
    var i = ~~(h * 6);
    var f = h * 6 - i;
    var q = 1 - f;
    switch(i % 6){
        case 0: r = 1; g = f; b = 0; break;
        case 1: r = q; g = 1; b = 0; break;
        case 2: r = 0; g = 1; b = f; break;
        case 3: r = 0; g = q; b = 1; break;
        case 4: r = f; g = 0; b = 1; break;
        case 5: r = 1; g = 0; b = q; break;
    }
    var c = "#" + ("00" + (~ ~(r * 255)).toString(16)).slice(-2) + ("00" + (~ ~(g * 255)).toString(16)).slice(-2) + ("00" + (~ ~(b * 255)).toString(16)).slice(-2);
    return (c);
}

Ответы [ 3 ]

2 голосов
/ 27 мая 2020

Нелегко иметь 32 цвета, которые действительно выглядят уникально. Особенно, если все, что вы хотите сделать, это изменить оттенок, вы можете увидеть здесь 32 цвета, меняющие только оттенок

enter image description here

const hsl = (h, s, l) => `hsl(${h * 360 | 0},${s * 100}%,${l * 100}%)`;
for (let i = 0; i < 32; ++i) {
  const div = document.createElement('div');
  div.style.background = hsl(i / 32, 1, 0.5);
  div.className = 'b';
  document.body.appendChild(div);
}
.b {
 width: 32px;
 height: 32px;
 display: inline-block;
}

Вы можете попробовать использовать другое цветовое пространство, например HCL, но это не менее проблематично c

enter image description here

for (let i = 0; i < 32; ++i) {
  const div = document.createElement('div');
  div.style.background  = chroma.hcl(i / 32 * 360, 80, 70).css();
  div.className = 'b';
  document.body.appendChild(div);
}
.b {
 width: 32px;
 height: 32px;
 display: inline-block;
}
<script src="https://cdn.jsdelivr.net/npm/chroma-js@2.1.0/chroma.min.js"></script>

Я бы посоветовал вам подумать об изменении яркости. Например, 16 светлых цветов и 16 темных цветов

Но больше я бы посоветовал, что бы вы ни делали, подумайте о добавлении узоров. Например, плоскость, клетка, вертикальные полосы, горизонтальные полосы, диагональные полосы, ромбы, и т.д. c ...

enter image description here

Или символы ♠ ️ ♦ ️ ♣ ️ ♥ ◾️ ● ▲ et c ..

Что касается выбора цветов с наибольшим расстоянием, вы можете поменять местами биты int, но вам нужно выбрать диапазон заранее. Например, если мы выберем диапазон от 0 до 255 (8 бит), то, поменяв местами биты, первые 2 элемента будут на максимальном расстоянии друг от друга. (0 и 128). Следующие 2 будут максимальным расстоянием между этими 2 (64 и 192). Следующие 4 будут максимальным значением между каждым из этих (32, 96, 160, 224), et c ...

См. this

1 голос
/ 27 мая 2020

Я нашел пример, но не понимаю, как его можно использовать

Вам нужно решить, на сколько разных сегментов вы хотите разделить свой градиент. Затем вам нужно l oop поверх этого total и сгенерируйте каждый сегмент градиента следующим образом:

function rainbow(numOfSteps, step) {
    // This function generates vibrant, "evenly spaced" colours (i.e. no clustering). This is ideal for creating easily distinguishable vibrant markers in Google Maps and other apps.
    // Adam Cole, 2011-Sept-14
    // HSV to RBG adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
    var r, g, b;
    var h = step / numOfSteps;
    var i = ~~(h * 6);
    var f = h * 6 - i;
    var q = 1 - f;
    switch(i % 6){
        case 0: r = 1; g = f; b = 0; break;
        case 1: r = q; g = 1; b = 0; break;
        case 2: r = 0; g = 1; b = f; break;
        case 3: r = 0; g = q; b = 1; break;
        case 4: r = f; g = 0; b = 1; break;
        case 5: r = 1; g = 0; b = q; break;
    }
    var c = "#" + ("00" + (~ ~(r * 255)).toString(16)).slice(-2) + ("00" + (~ ~(g * 255)).toString(16)).slice(-2) + ("00" + (~ ~(b * 255)).toString(16)).slice(-2);
    return (c);
}

const total = 100;
for (let i = 0; i < total; i++) {
  const $div = document.createElement('div');
  $div.className = 'box';
  $div.style.background = rainbow(total, i);
  document.body.appendChild($div);
}
.box {
  position: relative;
  width: 100%;
  height: 10px;
}
0 голосов
/ 27 мая 2020

Если вы хотите сохранить оттенок, было бы проще начать как HSV / HSL, а затем преобразовать в RGB:

    function generateHslaColors (saturation, lightness, alpha, amount) {
      let colors = []
      let huedelta = Math.trunc(360 / amount)

      for (let i = 0; i < amount; i++) {
        let hue = i * huedelta
        colors.push(`hsla(${hue},${saturation}%,${lightness}%,${alpha})`)
      }

      return colors
    }
    /**
     * Converts an HSL color value to RGB. Conversion formula
     * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
     * Assumes h, s, and l are contained in the set [0, 1] and
     * returns r, g, and b in the set [0, 255].
     *
     * @param   {number}  h       The hue
     * @param   {number}  s       The saturation
     * @param   {number}  l       The lightness
     * @return  {Array}           The RGB representation
     */
    function hslToRgb(h, s, l){
        var r, g, b;

        if(s == 0){
            r = g = b = l; // achromatic
        }else{
            var hue2rgb = function hue2rgb(p, q, t){
                if(t < 0) t += 1;
                if(t > 1) t -= 1;
                if(t < 1/6) return p + (q - p) * 6 * t;
                if(t < 1/2) return q;
                if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
                return p;
            }

            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
            var p = 2 * l - q;
            r = hue2rgb(p, q, h + 1/3);
            g = hue2rgb(p, q, h);
            b = hue2rgb(p, q, h - 1/3);
        }

        return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
    }
...