【问题标题】:How can I generate random shades of an RGB?如何生成 RGB 的随机阴影?
【发布时间】:2022-01-08 11:01:51
【问题描述】:

我正在尝试找到一种方法来生成 RGB 颜色的随机阴影。

正如您在 sn-p 中看到的,大多数色调都还可以,但有些颜色在视觉上完全不相关。有办法改善吗?

let resultsContainer = document.getElementById('results')
let original = { r: 244, g: 102, b: 255 } // generate random shades of this color
let max = 100
let min = 100
let results = []

document.getElementById('original').style.background = `rgb(${original.r}, ${original.g}, ${original.b})`

function randomBetween(min, max) {
  min = min < 0 ? 0 : min
  max = max > 255 ? 255 : max
  return min + Math.floor(Math.random() * (max - min + 1))
}


while (results.length < 10) {
  results.push({
    r: randomBetween(original.r-min, original.r+max),
    g: randomBetween(original.g-min, original.g+max),
    b: randomBetween(original.b-min, original.b+max),
  })
}


results.forEach(({ r, g, b }) => {
  let result = document.createElement('div')
  result.className = 'result'
  result.style.background = `rgb(${r}, ${g}, ${b})`
  resultsContainer.appendChild(result)
})
.result {
  float:left;
  width: 50px;
  height: 50px;
}
<div id="original" class="result"></div>
<br>
<br>
<br>
<br>
<div id="results"></div>

【问题讨论】:

  • 最好有大量预先批准的颜色,然后从中随机提取以避免出现多个灰色。
  • 无关紧要是什么意思?
  • @ggorlen 在视觉上无关
  • 毫不奇怪,每个色调,乍一看只有 5-6 个可区分的亮度级别。并且仅对于最上面的一个,您有 3 个可区分的饱和度级别,而较低的亮度值则按比例减少。因此,只有 12 种可感知的颜色才会有单一的色调可供选择。所有这些你都可以在 HSV 颜色空间中系统地构建。
  • 抱歉,我仍然不确定“视觉相关性”对您意味着什么。灰太多了?重叠/相似的颜色太多?

标签: javascript node.js colors rgb


【解决方案1】:

最好使用 HSL(Hue ,Saturation ,Lightness) 而不是 RGB ,并且只随机化 Saturation 和 Lightness 以获得不同的色调。

更新:根据 OP 建议更新代码,HSLRGB 转换器采用here

  function hslToRgb(h, s, l) {
      h /= 360.0, s /= 100.0, l /= 100.0;
      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)];
  }

  function rgbToHsl(r, g, b) {
      r /= 255, g /= 255, b /= 255;
      var max = Math.max(r, g, b),
          min = Math.min(r, g, b);
      var h, s, l = (max + min) / 2;

      if(max == min) {
          h = s = 0; // achromatic
      } else {
          var d = max - min;
          s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
          switch(max) {
              case r:
                  h = (g - b) / d + (g < b ? 6 : 0);
                  break;
              case g:
                  h = (b - r) / d + 2;
                  break;
              case b:
                  h = (r - g) / d + 4;
                  break;
          }
          h /= 6;
      }

      return [h * 360, s * 100, l * 100]
  }

  function randomBetween(min, max) {
      min = min < 10 ? 10 : min // under 10 it becomes too dark
      max = max > 90 ? 90 : max // over 90 it becomes too light
      return min + Math.floor(Math.random() * (max - min + 1))
  }

  let resultsContainer = document.getElementById('results')

  let originalAsRGB = [244, 102, 255]

  let originalAsHSL = rgbToHsl(
      originalAsRGB[0],
      originalAsRGB[1],
      originalAsRGB[2]
  )

  let max = 40
  let min = 40
  let results = []

  document.getElementById('original-as-rgb')
      .style.background =
      `rgb(${originalAsRGB[0]}, ${originalAsRGB[1]}, 
      ${originalAsRGB[2]})`

  document.getElementById('original-as-hsl')
      .style.background =
      `hsl(${originalAsHSL[0]}deg, ${originalAsHSL[1]}%, 
       ${originalAsHSL[2]}%)`


  while(results.length < 10) {
      results.push({
          h: originalAsHSL[0],
          s: randomBetween(originalAsHSL[1] - min, originalAsHSL[1] +
              max),
          l: randomBetween(originalAsHSL[2] - min, originalAsHSL[2] +
              max)
      })
  }


  results.forEach(({h,s,l}) => {
      let result = document.createElement('div')
      result.className = 'result'
      let [r, g, b] = hslToRgb(h, s, l)
      result.style.background = `rgb(${r}, ${g}, ${b})`
      resultsContainer.appendChild(result)
  })
.result {
  float:left;
  width: 50px;
  height: 50px;
}
<strong>original RGB:</strong>
<br>
<div id="original-as-rgb" class="result"></div>
<br>
<br>
<br>
<br>
<strong>original RGB converted to HSL:</strong>
<br>
<div id="original-as-hsl" class="result"></div>
<br>
<br>
<br>
<br>
<strong>random shades of the above HSL:</strong>
<br>
<div id="results"></div>

【讨论】:

  • 我现在的问题是我需要将 RGB 转换为 HSL。我找不到这样做的方法。
  • @SproutCoder 有一个很好的解决方案here,但是你可能需要做一些转换
  • @SproutCoder 抱歉回复迟了,在 jsfiddle 中,第 44 行必须是:return [h*360, s*100, l*100];
  • @SproutCoder 哈哈,我们在不同的时区,答案更新了,唯一的变化是在hslToRgb的开头添加以下内容=> h /= 360.0, s /= 100.0, l /= 100.0;
  • 感谢您花时间更新
【解决方案2】:

要对 RGB 进行着色,请将每个 r、g、b 乘以一个百分比。 要着色,对于每个 r、g、b,使用:color + value% * (255 - color)。 轻松愉快。

【讨论】:

    猜你喜欢
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 2021-04-14
    • 2020-03-17
    • 1970-01-01
    相关资源
    最近更新 更多