产品:”给我生成10000种不重复的背景色,上面的文字要能看清楚“

169 阅读2分钟

背景

产品:有一个需求,根据返回数据生成带背景色的色块,数据会很多,颜色随机生成并且不能重复,然后色块上的数字要看的清楚,要求文字颜色和背景色不能接近,应该不难吧...

我:“xxxxxxxxx”

image.png

好吧,能咋办呢,面向领导开发,打工人只能硬着头皮开(百)发(度)呗,吐槽一下,有些pm是产品经理,有些pm只是个画原型和传达需求的。

思路

我们平常使用的颜色无非就是通过 红色(R)、绿色(G)和蓝色(B)三个维度随机混合成不同的颜色,所以通过随机数,来生成16进制的颜色

代码实现

tips:通过亮度的差异对比,0.5是一个经验值,它代表了人眼的对比度敏感度,根据人类视觉的生理特点,相对亮度介于0.45到0.65之间的颜色,对于黑白对比度的敏感度较高,容易产生视觉渐近效应,因此0.5是一个相对缓和的中间值,适用于大多数场景。(相关资料查阅)

具体来说,如果颜色的相对亮度luminance大于0.5,则说明颜色比较浅,本身已经趋于白色,此时使用黑色作为前景色能够更好地提高视觉对比度,保证文本的易读性。如果颜色的相对亮度小于等于0.5,则说明颜色比较深,本身已经趋于黑色,此时使用白色作为前景色能够更好地提高视觉对比度

完整代码

function generateColors(numColors) {
  let colors = [];
  while (colors.length < numColors) {
    const color = generateRandomColor(); // 生成随机颜色
    if (!colors.includes(color)) {
      const luminance = calculateColorLuminance(color); // 计算颜色的相对亮度
      const labelColor = (luminance > 0.5) ? '#000000' : '#FFFFFF'; // 根据相对亮度自适应前景色
      colors.push({background: color, labelColor: labelColor});
    }
  }
  return colors;
}

function generateRandomColor() {
  // letters 是一个包含16个元素的字符串,用于生成16进制的颜色代码
  const letters = '0123456789ABCDEF';
  let color = '#';
  for (let i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

function calculateColorLuminance(color) {
  color = color.substr(1);
  const rgb = parseInt(color, 16);
  const r = (rgb >> 16) & 0xff; // red
  const g = (rgb >> 8) & 0xff; // green
  const b = (rgb >> 0) & 0xff; // blue

  const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
  return luminance / 255;
}

calculateColorLuminance,用于计算颜色的相对亮度,然后通过比较相对亮度来自适应选择字体颜色。(按照WCAG2.0标准进行计算,将颜色的RGB值转换为相对亮度值(0~1.0),最终返回相对亮度值)

const colors = generateColors(100); // 生成100种随机颜色
console.log(colors);

{
  background: '#FFFF00',
  labelColor: '#000000'
}

最后

通过上面的方案最终完美的交差,通过相关资料的查询也学到了蛮多。补充一句,上面一些思路和代码都是通过openAI生成的,对ai智能发自肺腑的感叹!(cv工程师以后可能也难做了)