如何生成 RGB 的随机阴影?

Posted

技术标签:

【中文标题】如何生成 RGB 的随机阴影?【英文标题】:How can I generate random shades of an 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>
我的 randomBetween() 方法的灵感来自 https://***.com/a/23095771/2272048

【问题讨论】:

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

【讨论】:

以上是关于如何生成 RGB 的随机阴影?的主要内容,如果未能解决你的问题,请参考以下文章

JS生成随机颜色(rgb)

创建的每个实例的随机颜色生成器和 RGB [重复]

JavaScript随机生成颜色以及十六进制颜色 与RGB颜色值的相互转换

如何生成随机验证码

python 随机生成图片验证码背景RGB-浅色或者深色

PHP生成RGB