66 votes

Dégradé de couleurs en Javascript

En utilisant javascript avec ou sans Jquery, je dois créer un gradient de couleurs à partir d'une couleur de départ et d'arrivée. Est-ce possible de le faire par programme ?

La couleur finale ne sera jamais qu'une nuance plus foncée de la couleur de départ et c'est pour une liste non ordonnée dont je n'ai aucun contrôle sur le nombre d'éléments. Je cherche une solution qui me permette de choisir une couleur de début et de fin, de convertir la valeur hexadécimale en RVB afin de pouvoir la manipuler dans le code. Les valeurs RVB de départ sont incrémentées d'une valeur progressive calculée en fonction du nombre d'éléments.

Ainsi, si la liste comporte 8 éléments, il faut incrémenter les valeurs rouge, vert et bleu en 8 étapes pour obtenir la couleur finale. Existe-t-il une meilleure façon de procéder et si oui, où puis-je trouver un exemple de code ?

1 votes

Ce que vous décrivez est la façon dont je le ferais : il suffit de faire une interpolation linéaire entre les points de départ et d'arrivée pour chacune des trois composantes de couleur.

2 votes

Veuillez noter qu'il existe différents types de dégradés : si vous souhaitez réaliser un dégradé qui passe par le rouge -> jaune -> vert -> bleu, vous devrez probablement obtenir les valeurs HSL plutôt que les valeurs RGB.

5voto

m13r Points 1401

Il existe une bibliothèque JavaScript qui permet de créer des dégradés de couleurs :

javascript-color-gradient

import Gradient from "javascript-color-gradient";
const colorGradient = new Gradient();
colorGradient.setGradient("#e6062d", "#408247"); // from red to green
colorGradient.setMidpoint(8); // set to 8 color steps
colorGradient.getArray(); // get all 8 colors: [ "#d11630", "#bd2534", ... ]
colorGradient.getColor(1); // #bd2534

resulting color gradient

4voto

AlonR Points 565

Basé sur la réponse de @drinor - support TypeScript

const getGradientColor = (startColor: string, endColor: string, percent: number) => {
    // strip the leading # if it's there
    startColor = startColor.replace(/^\s*#|\s*$/g, '');
    endColor = endColor.replace(/^\s*#|\s*$/g, '');

    // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
    if (startColor.length === 3) {
      startColor = startColor.replace(/(.)/g, '$1$1');
    }

    if (endColor.length === 3) {
      endColor = endColor.replace(/(.)/g, '$1$1');
    }

    // get colors
    const startRed = parseInt(startColor.substr(0, 2), 16),
      startGreen = parseInt(startColor.substr(2, 2), 16),
      startBlue = parseInt(startColor.substr(4, 2), 16);

    const endRed = parseInt(endColor.substr(0, 2), 16),
      endGreen = parseInt(endColor.substr(2, 2), 16),
      endBlue = parseInt(endColor.substr(4, 2), 16);

    // calculate new color
    let diffRed = endRed - startRed;
    let diffGreen = endGreen - startGreen;
    let diffBlue = endBlue - startBlue;

    diffRed = ((diffRed * percent) + startRed);
    diffGreen = ((diffGreen * percent) + startGreen);
    diffBlue = ((diffBlue * percent) + startBlue);

    let diffRedStr = diffRed.toString(16).split('.')[0];
    let diffGreenStr = diffGreen.toString(16).split('.')[0];
    let diffBlueStr = diffBlue.toString(16).split('.')[0];

    // ensure 2 digits by color
    if (diffRedStr.length === 1) diffRedStr = '0' + diffRedStr;
    if (diffGreenStr.length === 1) diffGreenStr = '0' + diffGreenStr;
    if (diffBlueStr.length === 1) diffBlueStr = '0' + diffBlueStr;

    return '#' + diffRedStr + diffGreenStr + diffBlueStr;
}

exemple :

getGradientColor('#FF0000', '#00FF00', 0.4);

\=> "#996600"

3voto

B T Points 4868

El bibliothèque xolor a une fonction de gradient. Cela créera un tableau avec 8 couleurs dans un gradient d'une couleur de début à une couleur de fin :

var gradientColors = []
var startColor = "rgb(100,200,50)", endColor = "green"
var start = xolor(startColor)
for(var n=0; n<8; n++) {
   gradientColors.push(start.gradient(endColor, n/8))
}  

Voir plus sur github : https://github.com/fresheneesz/xolor

1voto

r00tandy Points 38

Pas si puissant que cela, mais dans la plupart des cas, cela fonctionne et vous ne devez pas inclure d'autres bibliothèques que jQuery pour le code suivant :

HTML :

<div id="colors"></div>

JavaScript :

function rainbow(value, s, l, max, min, start, end) {
    value = ((value - min) * (start - end) / max)+end;
    return 'hsl(' + value + ','+s+'%,'+l+'%)';
}

function createRainbowDiv(start,end){
    var gradient = $("<div>").css({display:"flex", "flex-direction":"row",height:"100%"});
    for (var i = start; ((i <= end) && (i >= start)) || ((i >= end) && (i <= start)); 
        i += (end-start) / Math.abs(end-start)){
            gradient.append($("<div>").css({float:"left","background-color":rainbow(i, 100,50, Math.max(start,end), Math.min(start,end), start,end),flex:1}));
    }

    return gradient;
}

$("#colors").append(createRainbowDiv(0,150));
$("#colors").css("width","100%").css("height","10px");

Cela devrait créer une div qui contient un arc-en-ciel. Voir http://jsfiddle.net/rootandy/54rV7/

1voto

theHaymaker Points 11

Je devais créer un éventail suffisamment large d'options de couleurs pour un ensemble inconnu d'éléments dynamiques, mais j'avais besoin que chaque élément s'incrémente en passant par une couleur de début et une couleur de fin. Cela suit en quelque sorte l'approche du "pourcentage de fondu", sauf que j'ai eu du mal à suivre cette logique. Voici comment je l'ai abordé en utilisant des entrées de deux valeurs de couleur rgb et en calculant le nombre d'éléments sur la page.

Voici un lien vers un codepen qui démontre le concept.

Vous trouverez ci-dessous un extrait de code illustrant le problème.

    <style>
      #test {
          width:200px;
          height:100px;
          border:solid 1px #000;
      }

      .test {
          width:49%;
          height:100px;
          border:solid 1px #000;
          display: inline-block;
      }
    </style>
</head>
<body>

<div id="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

    <script>

      var GColor = function(r,g,b) {
          r = (typeof r === 'undefined')?0:r;
          g = (typeof g === 'undefined')?0:g;
          b = (typeof b === 'undefined')?0:b;
          return {r:r, g:g, b:b};
      };

      // increases each channel by the difference of the two
      // divided by 255 (the number of colors stored in the range array)
      // but only stores a whole number
      // This should respect any rgb combinations
      // for start and end colors

      var createColorRange = function(c1) {
          var colorList = [], tmpColor, rr = 0, gg = 0, bb = 0;
          for (var i=0; i<255; i++) {
            tmpColor = new GColor();
              if (rExp >= 0) {

                tmpColor.r = Math.floor(c1.r - rr);
                rr += rAdditive;

              } else {

                tmpColor.r = Math.floor(c1.r + rr);
                rr += rAdditive;
              }

              if (gExp >= 0) {

                tmpColor.g = Math.floor(c1.g - gg);
                gg += gAdditive;

              } else {

                tmpColor.g = Math.floor(c1.g + gg);
                gg += gAdditive;
              }

              if (bExp >= 0) {

                tmpColor.b = Math.floor(c1.b - bb);
                bb += bAdditive;

              } else {

                tmpColor.b = Math.floor(c1.b + bb);
                bb += bAdditive;

              }

              console.log(tmpColor);

              colorList.push(tmpColor);
          }
          return colorList;
      };

      /* ==================
         Testing Code Below
         ================== */

      var firstColor = new GColor(255, 24, 0);
      var secondColor = new GColor(255, 182, 0);

      // Determine the difference
      var rExp = firstColor.r - secondColor.r;

      // Divide that difference by length of the array
      // you would like to create (255 in this case)
      var rAdditive = Math.abs(rExp)/255;

      var gExp = firstColor.g - secondColor.g;
      var gAdditive = Math.abs(gExp)/255;

      var bExp = firstColor.b - secondColor.b;
      var bAdditive = Math.abs(bExp)/255;

      var range = createColorRange(firstColor, secondColor);
      console.log(range);
      var pointer = 0;

      // This gently cycles through
      // all the colors on a single element
      function rotateColors() {
          var currentColor = range[pointer];
          document.getElementById("test").style.backgroundColor = "rgb("+currentColor.r+","+currentColor.g+","+currentColor.b+")";
          pointer++;
          if (pointer < range.length) window.setTimeout(rotateColors, 5);
      }

       rotateColors();

      // say I have 5 elements
      // so I need 5 colors
      // I already have my first and last colors
      // but I need to locate the colors between
      // my start color and my end color
      // inside of this range
      // so I divide the range's length by the
      // number of colors I need
      // and I store the index values of the middle values

      // those index numbers will then act as my keys to retrieve those values
      // and apply them to my element

      var myColors = {};
      var objects = document.querySelectorAll('.test');
        myColors.num = objects.length;

      var determineColors = function(numOfColors, colorArray) {
        var colors = numOfColors;

        var cRange = colorArray;
        var distance = Math.floor(cRange.length/colors);
        var object = document.querySelectorAll('.test');

        var j = 0;
        for (var i = 0; i < 255; i += distance) {

          if ( (i === (distance*colors)) ) {
            object[j].style.backgroundColor = "rgb(" + range[255].r + ", " + range[255].g + ", " + range[255].b + ")";

            j = 0;
            // console.log(range[i]);
          } else {

                // Apply to color to the element
                 object[j].style.backgroundColor = "rgb(" + range[i].r + ", " + range[i].g + ", " + range[i].b + ")";

                  // Have each element bleed into the next with a gradient
               // object[j].style.background = "linear-gradient( 90deg, rgb(" + range[i].r + ", " + range[i].g + ", " + range[i].b + "), rgb(" + range[i+distance].r + ", " + range[i+distance].g + ", " + range[i+distance].b + "))";

            j++;
          }

        }
      };

      setTimeout( determineColors(myColors.num, range), 2000);

    </script>
</body>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X