【问题标题】:how to make a color similar to another color by percentage in Javascript如何在Javascript中按百分比使颜色与另一种颜色相似
【发布时间】:2015-03-17 00:02:27
【问题描述】:

我有两种十六进制颜色,#000000#ffffff。我想按百分比将第一种颜色近似为第二种颜色。 类似的东西:

var percent=0.50;
var color1='#000000';
var color2='#ffffff';

var newcolor=approximateColor1ToColor2ByPercent(color1,color2,percent);
//newcolor should be a gray like #808080

如何做到这一点?

【问题讨论】:

标签: javascript css


【解决方案1】:

ES6 实现:

其实我只是用ES6重写了这篇文章的正确答案,并用TypeScript语言输入:

const generateHex = (r: number, g: number, b: number): string => {
  let R = r.toString(16);
  let G = g.toString(16);
  let B = b.toString(16);

  while (R.length < 2) {
    R = `0${R}`;
  }
  while (G.length < 2) {
    G = `0${G}`;
  }
  while (B.length < 2) {
    B = `0${B}`;
  }

  return `#${R}${G}${B}`;
};

const mix = (start: number, end: number, percent: number): number =>
    start + (percent / 100) * (end - start);

const blender = (color1: string, color2: string, percent: number): string => {
  const red1 = parseInt(`${color1[1]}${color1[2]}`, 16);
  const green1 = parseInt(`${color1[3]}${color1[4]}`, 16);
  const blue1 = parseInt(`${color1[5]}${color1[6]}`, 16);

  const red2 = parseInt(`${color2[1]}${color2[2]}`, 16);
  const green2 = parseInt(`${color2[3]}${color2[4]}`, 16);
  const blue2 = parseInt(`${color2[5]}${color2[6]}`, 16);

  const red = Math.round(mix(red1, red2, percent));
  const green = Math.round(mix(green1, green2, percent));
  const blue = Math.round(mix(blue1, blue2, percent));

  return generateHex(red, green, blue);
};

export default blender;

注意blender 函数将两个给定颜色与 百分比数字 合并,这意味着百分比数字应该在 0 ~ 100 之间,您可以使用以下代码进行测试:

document.body.style.backgroundColor = blender('#ffffff', '#ff0000', 30);

【讨论】:

    【解决方案2】:

    对于加色混合:

    要混合两种颜色,请执行以下操作:

    function approximateColor1ToColor2ByPercent(color1, color2, percent) {
      var red1 = parseInt(color1[1] + color1[2], 16);
      var green1 = parseInt(color1[3] + color1[4], 16);
      var blue1 = parseInt(color1[5] + color1[6], 16);
    
      var red2 = parseInt(color2[1] + color2[2], 16);
      var green2 = parseInt(color2[3] + color2[4], 16);
      var blue2 = parseInt(color2[5] + color2[6], 16);
    
      var red = Math.round(mix(red1, red2, percent));
      var green = Math.round(mix(green1, green2, percent));
      var blue = Math.round(mix(blue1, blue2, percent));
    
      return generateHex(red, green, blue);
    }
    
    function generateHex(r, g, b) {
      r = r.toString(16);
      g = g.toString(16);
      b = b.toString(16);
    
      // to address problem mentioned by Alexis Wilke:
      while (r.length < 2) { r = "0" + r; }
      while (g.length < 2) { g = "0" + g; }
      while (b.length < 2) { b = "0" + b; }
    
      return "#" + r + g + b;
    }
    
    function mix(start, end, percent) {
        return start + ((percent) * (end - start));
    }
    

    那么下面的代码:

    approximateColor1ToColor2ByPercent('#000000', '#ffffff', .50);
    

    将返回'#808080'

    【讨论】:

    • 这会将黄色+蓝色混合成灰色,这可能是也可能不是想要的。还有许多其他可能的混合颜色算法。
    • @Stuart - 我刚刚意识到,在加色模型上混合纯黄色和蓝色等颜色时,会产生灰色。这是因为您基本上混合了 50% 的红色、50% 的绿色和 50% 的蓝色。您可能需要查看减法混合,我将在我的答案中提出。
    • 如果结果颜色在 0 到 15 (0x0F) 之间会发生什么?
    • @AlexisWilke - 是的,这是我要解决的另一件事。谢谢。
    【解决方案3】:

    我不专业,只是分享我的努力。

    大自然和电脑表现颜色的方式不同。要获得与您想要的颜色相似的颜色,您可以使用浅蓝色(#00FFFF)而不是(#OOOOFF)。

    所以我尝试了两种颜色混合的方式,第一种是传统的加法混合:

    newColor.R = (color1.R + color2.R)/2
    

    对于 alpha 混合,color1 和 color2 都有自己的 alpha 通道,代表自身的透明度。所以 alpha 混合算法应该是这样的(R,G,B 范围从 0 到 255):

    newAlpha = 1 - (1-color1.Alpha) * (1-color2.Alpha)
    newColor.R = (color1.R/255 * color1.Alpha / newAlpha + color2.R/255 * color2.Alpha * (1-color1.Alpha) / newAlpha)*255
    

    我已经实现了,你可以看到结果:

    //Convert hex color into rgb color
    function HexToRgb(hexcolor) {
      var hexR = hexcolor.substr(0, 2);
      var hexG = hexcolor.substr(2, 2);
      var hexB = hexcolor.substr(4, 2);
      var rgbColor = [];
      rgbColor[0] = parseInt(hexR, 16);
      rgbColor[1] = parseInt(hexG, 16);
      rgbColor[2] = parseInt(hexB, 16);
      return rgbColor;
    }
    
    //Convert rgb color int hex color
    function RgbtoHex(rgbcolor) {
      var hexColor = rgbcolor[0].toString(16) + rgbcolor[1].toString(16) + rgbcolor[2].toString(16);
      return hexColor;
    }
    
    //Additive mixing two colors
    function additiveMixing(color1, color2) {
      var rgbColor1 = HexToRgb(arguments[0]);
      var rgbColor2 = HexToRgb(arguments[1]);
    
      var newColor = [];
      for (var n = 0; n < 3; n++) {
        newColor[n] = Math.round((rgbColor1[n] + rgbColor2[n]) / 2);
      }
      return RgbtoHex(newColor);
    }
    
    //Alpha blending two colors with two alphas
    function alphaBlending(color1, color2, alpha1, alpha2) {
      var rgbColor1 = HexToRgb(arguments[0]);
      var rgbColor2 = HexToRgb(arguments[1]);
    
      var newColor = [];
      var alpha1 = arguments[2];
      var alpha2 = arguments[3];
      var alpha = 1 - (1 - alpha1) * (1 - alpha2);
      for (var n = 0; n < 3; n++) {
        newColor[n] = Math.round((rgbColor1[n] / 255.0 * alpha1 / alpha + rgbColor2[n] / 255.0 * alpha2 * (1 - alpha1) / alpha) * 255);
      }
      return RgbtoHex(newColor);
    }
    
    //Show base color change
    $("#color1, #color2").change(function() {
      var color = $(this).val();
      $(this).next().css("background-color", color);
    });
    
    //Mix color
    $("button").click(function() {
      var color1 = $("#color1").val().substr(1);
      var color2 = $("#color2").val().substr(1);
      var alpha1 = parseFloat($("#alpha1").val());
      var alpha2 = parseFloat($("#alpha2").val());
      var additiveColor = additiveMixing(color1, color2);
      var alphablendColor = alphaBlending(color1, color2, alpha1, alpha2);
    
      $("#additive span").text("#" + additiveColor);
      $("#additive span").parent().next().css("background-color", "#" + additiveColor);
    
      $("#alpha span").text("#" + alphablendColor);
      $("#alpha span").parent().next().css("background-color", "#" + alphablendColor);
    });
    .color_block {
      width: 50px;
      height: 20px;
      margin-top: 5px;
      border: 1px solid black;
    }
    #result {
      position: absolute;
      top: 15px;
      left: 240px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <ul>
      <li>
        <label for="color1">Color 1</label>
        <br/>
        <input id="color1" type="text" value="#00FFFF" />
        <div class="color_block" style="background-color: #0000FF;"></div>
      </li>
      <li>
        <label for="color2">Color 2</label>
        <br/>
        <input id="color2" type="text" value="#FFFF00" />
        <div class="color_block" style="background-color: #FFFF00;"></div>
      </li>
      <li>
        <label for="alpha1">Alpha 1(0-1)</label>
        <br/>
        <input id="alpha1" type="text" value="0.5" />
      </li>
      <li>
        <label for="alpha2">Alpha 2(0-1)</label>
        <br/>
        <input id="alpha2" type="text" value="0.5" />
      </li>
    </ul>
    <br>
    <button>Mix them!</button>
    <div id="result">
      <p id="additive">Additive mixed color is <span>N/A</span>
      </p>
      <div class="color_block"></div>
      <p id="alpha">Alpha blending mixed color is <span>N/A</span>
      </p>
      <div class="color_block"></div>
    </div>

    参考:

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 2016-08-03
    • 2011-05-23
    • 2019-01-29
    • 2018-12-05
    • 1970-01-01
    • 2012-02-18
    相关资源
    最近更新 更多