Calculate color HEX having 2 colors and percent/position

前端 未结 4 445
野性不改
野性不改 2020-12-25 13:52

Is it possible to calculate a color in a middle of a gradient?

var color1 = \'FF0000\';
var color2 = \'00FF00\';

// 50% between the two colors, should retur         


        
相关标签:
4条回答
  • 2020-12-25 14:31

    I can't comment on the answer above, so I write it here:

    I found out that in the Javascript substring method the to parameter index is not included in the returned string. That means:

    var string = "test";
    //index:      0123
    alert(string.substring(1,3));
    
    //will alert es and NOT est
    

    Edit: So it should be:

    parseInt(color1.substring(0,2), 16);
    parseInt(color1.substring(2,4), 16);
    

    and

    parseInt(color1.substring(4,6), 16);
    
    0 讨论(0)
  • 2020-12-25 14:35

    You can use this ready function (ES6):

    const calculateMiddleColor = ({
      color1 = 'FF0000',
      color2 = '00FF00',
      ratio,
    }) => {
      const hex = (color) => {
        const colorString = color.toString(16);
        return colorString.length === 1 ? `0${colorString}` : colorString;
      };
    
      const r = Math.ceil(
        parseInt(color2.substring(0, 2), 16) * ratio
          + parseInt(color1.substring(0, 2), 16) * (1 - ratio),
      );
      const g = Math.ceil(
        parseInt(color2.substring(2, 4), 16) * ratio
          + parseInt(color1.substring(2, 4), 16) * (1 - ratio),
      );
      const b = Math.ceil(
        parseInt(color2.substring(4, 6), 16) * ratio
          + parseInt(color1.substring(4, 6), 16) * (1 - ratio),
      );
    
      return hex(r) + hex(g) + hex(b);
    };
    //////////////////////////////////////////////////////////////////////
    console.log(calculateMiddleColor({ ratio: 0 / 5 })); // ff0000
    console.log(calculateMiddleColor({ ratio: 5 / 5 })); // 00ff00
    console.log(calculateMiddleColor({ ratio: 2.5 / 5 })); // 808000
    console.log(calculateMiddleColor({ ratio: 4.2 / 5 })); // 29d700
    
    0 讨论(0)
  • 2020-12-25 14:36

    This should work:

    It basically involves converting them to decimal, finding the halves, converting the results back to hex and then concatenating them.

    var color1 = 'FF0000';
    var color2 = '00FF00';
    var ratio = 0.5;
    var hex = function(x) {
        x = x.toString(16);
        return (x.length == 1) ? '0' + x : x;
    };
    
    var r = Math.ceil(parseInt(color1.substring(0,2), 16) * ratio + parseInt(color2.substring(0,2), 16) * (1-ratio));
    var g = Math.ceil(parseInt(color1.substring(2,4), 16) * ratio + parseInt(color2.substring(2,4), 16) * (1-ratio));
    var b = Math.ceil(parseInt(color1.substring(4,6), 16) * ratio + parseInt(color2.substring(4,6), 16) * (1-ratio));
    
    var middle = hex(r) + hex(g) + hex(b);
    
    0 讨论(0)
  • 2020-12-25 14:40

    An ES6 version with comprehensions:

    function interpolateColor(c0, c1, f){
        c0 = c0.match(/.{1,2}/g).map((oct)=>parseInt(oct, 16) * (1-f))
        c1 = c1.match(/.{1,2}/g).map((oct)=>parseInt(oct, 16) * f)
        let ci = [0,1,2].map(i => Math.min(Math.round(c0[i]+c1[i]), 255))
        return ci.reduce((a,v) => ((a << 8) + v), 0).toString(16).padStart(6, "0")
    }
    

    As in the accepted answer, c0,c1 are color codes (without the leading #) and f is "progress" between the two values. (At f=0 this ends up returning c0, at f=1 this returns c1).

    • The first two lines convert the color codes into arrays of scaled integers
    • The third line:
      • "zips" the two integer arrays
      • sums the corresponding values
      • rounds the sum and clamps it to 0-255
    • The fourth line:
      • converts the integer array into a single integer (reduce and bitshifting)
      • converts the integer into its hexadecimal string form
      • ensures the resulting string is 6 characters long and returns it
    0 讨论(0)
提交回复
热议问题