How to get color value from gradient by percentage with javascript?

后端 未结 5 1112
离开以前
离开以前 2020-12-08 10:54

I have a fixed width div with gradient applied using css. I want to build slider based color picker based on this gradient.

When i drag the slider i calculate the pe

相关标签:
5条回答
  • 2020-12-08 11:33

    Three color gradient

    Just in case someone wants a 3 color gradient, here's an example using red, yellow and green:

    The github JS code for the colorGradient function is available here.

    function colorGradient(fadeFraction, rgbColor1, rgbColor2, rgbColor3) {
        var color1 = rgbColor1;
        var color2 = rgbColor2;
        var fade = fadeFraction;
    
        // Do we have 3 colors for the gradient? Need to adjust the params.
        if (rgbColor3) {
          fade = fade * 2;
    
          // Find which interval to use and adjust the fade percentage
          if (fade >= 1) {
            fade -= 1;
            color1 = rgbColor2;
            color2 = rgbColor3;
          }
        }
    
        var diffRed = color2.red - color1.red;
        var diffGreen = color2.green - color1.green;
        var diffBlue = color2.blue - color1.blue;
    
        var gradient = {
          red: parseInt(Math.floor(color1.red + (diffRed * fade)), 10),
          green: parseInt(Math.floor(color1.green + (diffGreen * fade)), 10),
          blue: parseInt(Math.floor(color1.blue + (diffBlue * fade)), 10),
        };
    
        return 'rgb(' + gradient.red + ',' + gradient.green + ',' + gradient.blue + ')';
    }
    

    Demo:

    // Gradient Function
    function colorGradient(fadeFraction, rgbColor1, rgbColor2, rgbColor3) {
        var color1 = rgbColor1;
        var color2 = rgbColor2;
        var fade = fadeFraction;
    
        // Do we have 3 colors for the gradient? Need to adjust the params.
        if (rgbColor3) {
          fade = fade * 2;
    
          // Find which interval to use and adjust the fade percentage
          if (fade >= 1) {
            fade -= 1;
            color1 = rgbColor2;
            color2 = rgbColor3;
          }
        }
    
        var diffRed = color2.red - color1.red;
        var diffGreen = color2.green - color1.green;
        var diffBlue = color2.blue - color1.blue;
    
        var gradient = {
          red: parseInt(Math.floor(color1.red + (diffRed * fade)), 10),
          green: parseInt(Math.floor(color1.green + (diffGreen * fade)), 10),
          blue: parseInt(Math.floor(color1.blue + (diffBlue * fade)), 10),
        };
    
        return 'rgb(' + gradient.red + ',' + gradient.green + ',' + gradient.blue + ')';
    }
      
    // Implementation sample
    var spans = $('.gradient-test');
    var count = spans.length, color;
    var color1 = {
      red: 19, green: 233, blue: 19
    };
    var color2 = {
      red: 255, green: 0, blue: 0
    };
    var color3 = {
      red: 255, green: 255, blue: 0
    };
    $('.gradient-test').each(function(i, span) {
      var g = Math.round(((i+1) * 100) / count);
      if (g < 10){
        g = '0' + g;
      }
      g = +('0.' + g)
      color = colorGradient(g, color1, color2, color3);
      $(span).css('background-color', color);
    });
    .gradient-test {
      width: 1rem;
      height: 1rem;
      display: inline-block;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>
    <span class="gradient-test"></span>

    0 讨论(0)
  • 2020-12-08 11:37

    There is a nice lib that handles variety of color manipulations chroma.js

    yarn add chroma-js
    

    And then

    import chroma from 'chroma-js';
    
    const f = chroma.scale(['yellow', 'red', 'black']);
    
    console.log( f(0.25).toString() );                    // #ff8000
    console.log( f(0.5).css('rgba') );                    // rgba(255,0,0,1)
    console.log( f(0.75).css() );                         // rgb(128,0,0)
    console.log( f(1).css() );                            // rgb(0,0,0)
    
    0 讨论(0)
  • 2020-12-08 11:41

    I was able to solve this issue using this function, which is based on the less.js function: http://lesscss.org/functions/#color-operations-mix

    function pickHex(color1, color2, weight) {
        var w1 = weight;
        var w2 = 1 - w1;
        var rgb = [Math.round(color1[0] * w1 + color2[0] * w2),
            Math.round(color1[1] * w1 + color2[1] * w2),
            Math.round(color1[2] * w1 + color2[2] * w2)];
        return rgb;
    }
    

    I just simply need to pass the two closest color codes from the gradient array and the ratio where the slider handle is located(which can be calculated easily with the help of the slider width). Here is the live example:

    http://jsfiddle.net/vksn3yLL/

    0 讨论(0)
  • 2020-12-08 11:52

    This is another way to convert percentage to color

    This exemple make a displayed value change from red to green depending on it's value (like for example in excel conditional formating):

    function(percentValue) {
      $(`#output`)
        // print the value
        .html(percentValue)
        // colorize the text, more red if it's close to 0
        // and more green as it approach 100
        .css({color: `rgb(${(100 - percent) *2.56}, ${percent *2.56},0)`})
    }
    

    Please see demo below:

    $('button').click( e => {
      const percent = Math.floor(Math.random()*100);
      const newElm = $(`<b>${percent}</b><br>`)
      .css({color: `rgb(${(100 - percent) *2.56},${percent *2.56},0)`})
      $('body').append(newElm);
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <button>Click to make new percentage</button><br>

    0 讨论(0)
  • 2020-12-08 11:52

    Infinite number of colors gradient (two or more)

    If your have 2, 3, 4 or twenty colors you can use this solution. Generate an HTML element and style it with CSS gradient background. Then look at a single pixel color value.

    1. Create a <canvas> element. with width of 101px (0 to 100 percent) and height 1px (we don't care about height). Then set the background-color to gradient. See method initCanvas(colorsArray).

    2. Look at a single pixel of the canvas, and return it's color. See method getColor(percent).

    3. At the end you can find and example of gradient made from 5 colors (red, orange, green, lime, blue).

    const WIDTH = 101; // 0 to 100
    const HEIGHT = 1;
      
    let context;
    
    function initCanvas(gradientColors) // gradientColors [colorA, colorB, ..]
    {
      // Canvas
      const canvasElement = document.createElement("CANVAS");
      canvasElement.width = WIDTH;
      canvasElement.height = HEIGHT;
    
      context = canvasElement.getContext("2d");
      
      // Gradient
      const gradient = context.createLinearGradient(0, 0, WIDTH, 0); // x0, y0, x1, y1
      
      const step = 1 / (gradientColors.length - 1); // need to validate at least two colors in gradientColors
      let val = 0;
      gradientColors.forEach(color => {
        gradient.addColorStop(val, color);
        val += step;
      });
    
      // Fill with gradient
      context.fillStyle = gradient;
      context.fillRect(0, 0, WIDTH, HEIGHT); // x, y, width, height
    }
    
    function getColor(percent) // percent [0..100]
    {
      const color = context.getImageData(percent, 0, 1, 1); // x, y, width, height
      const rgba = color.data;
      
      return `rgb(${ rgba[0] }, ${ rgba[1] }, ${ rgba[2] })`;
    }
    
    // Test:
    initCanvas(['red', 'orange', 'green', 'lime', 'blue']);
    
    document.getElementById("color0"  ).style.backgroundColor = getColor(0);
    document.getElementById("color10" ).style.backgroundColor = getColor(10);
    document.getElementById("color20" ).style.backgroundColor = getColor(20);
    document.getElementById("color30" ).style.backgroundColor = getColor(30);
    document.getElementById("color40" ).style.backgroundColor = getColor(40);
    document.getElementById("color50" ).style.backgroundColor = getColor(50);
    document.getElementById("color60" ).style.backgroundColor = getColor(60);
    document.getElementById("color70" ).style.backgroundColor = getColor(70);
    document.getElementById("color80" ).style.backgroundColor = getColor(80);
    document.getElementById("color90" ).style.backgroundColor = getColor(90);
    document.getElementById("color100").style.backgroundColor = getColor(100);
    .example {
      width: 100px;
      height: 25px;
    }
    <h3>Gradient colors: red, orange, green, lime, blue</h3>
    <div id="color0"   class="example">0%  </div>
    <div id="color10"  class="example">10% </div>
    <div id="color20"  class="example">20% </div>
    <div id="color30"  class="example">30% </div>
    <div id="color40"  class="example">40% </div>
    <div id="color50"  class="example">50% </div>
    <div id="color60"  class="example">60% </div>
    <div id="color70"  class="example">70% </div>
    <div id="color80"  class="example">80% </div>
    <div id="color90"  class="example">90% </div>
    <div id="color100" class="example">100%</div>

    P.S - I code with two methods initCanvs() and getColors() so you won't generate new canvas for each color selection. But you can merge them if you have new gradient each time.

    0 讨论(0)
提交回复
热议问题