it-swarm.com.ru

Цветовой градиент Javascript

Используя JavaScript с или без Jquery, мне нужно создать градиент цветов на основе начального и конечного цветов. Это возможно сделать программно?

Конечный цвет будет только темнее оттенка начального цвета, и это для неупорядоченного списка, который я не могу контролировать количеством элементов li. Я ищу решение, которое позволит мне выбрать начальный и конечный цвет, преобразовать шестнадцатеричное значение в RGB, чтобы им можно было манипулировать в коде. Начальные значения RGB увеличиваются на значение шага, рассчитанное на основе количества элементов.

так что если в списке было 8 элементов, то для достижения окончательного цвета необходимо увеличить отдельные значения красного, зеленого, синего цветов за 8 шагов. Есть ли лучший способ сделать это, и если да, где я могу найти пример кода? 

41
Dave

Я создал библиотеку JS, RainbowVis-JS , чтобы решить эту общую проблему. Вам просто нужно установить количество элементов с помощью setNumberRange и установить начальный и конечный цвет с помощью setSpectrum. Затем вы получите шестнадцатеричный код цвета с помощью colourAt.

var numberOfItems = 8;
var Rainbow = new Rainbow(); 
Rainbow.setNumberRange(1, numberOfItems);
Rainbow.setSpectrum('red', 'black');
var s = '';
for (var i = 1; i <= numberOfItems; i++) {
    var hexColour = Rainbow.colourAt(i);
    s += '#' + hexColour + ', ';
}
document.write(s); 
// gives:
// #ff0000, #db0000, #b60000, #920000, #6d0000, #490000, #240000, #000000, 

Вы можете посмотреть исходный код библиотеки. :)

73
anomal

Правильная функция для генерации массива цветов!

function hex (c) {
  var s = "0123456789abcdef";
  var i = parseInt (c);
  if (i == 0 || isNaN (c))
    return "00";
  i = Math.round (Math.min (Math.max (0, i), 255));
  return s.charAt ((i - i % 16) / 16) + s.charAt (i % 16);
}

/* Convert an RGB triplet to a hex string */
function convertToHex (rgb) {
  return hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}

/* Remove '#' in color hex string */
function trim (s) { return (s.charAt(0) == '#') ? s.substring(1, 7) : s }

/* Convert a hex string to an RGB triplet */
function convertToRGB (hex) {
  var color = [];
  color[0] = parseInt ((trim(hex)).substring (0, 2), 16);
  color[1] = parseInt ((trim(hex)).substring (2, 4), 16);
  color[2] = parseInt ((trim(hex)).substring (4, 6), 16);
  return color;
}

function generateColor(colorStart,colorEnd,colorCount){

	// The beginning of your gradient
	var start = convertToRGB (colorStart);    

	// The end of your gradient
	var end   = convertToRGB (colorEnd);    

	// The number of colors to compute
	var len = colorCount;

	//Alpha blending amount
	var alpha = 0.0;

	var saida = [];
	
	for (i = 0; i < len; i++) {
		var c = [];
		alpha += (1.0/len);
		
		c[0] = start[0] * alpha + (1 - alpha) * end[0];
		c[1] = start[1] * alpha + (1 - alpha) * end[1];
		c[2] = start[2] * alpha + (1 - alpha) * end[2];

		saida.Push(convertToHex (c));
		
	}
	
	return saida;
	
}

// Exemplo de como usar


var tmp = generateColor('#000000','#ff0ff0',10);

for (cor in tmp) {
  $('#result_show').append("<div style='padding:8px;color:#FFF;background-color:#"+tmp[cor]+"'>COLOR "+cor+"° - #"+tmp[cor]+"</div>")
 
}
	
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result_show"></div>

28
Euler Junior

Да, конечно.

Я делаю это в Java, должно быть довольно просто сделать в JavaScript тоже.

Во-первых, вам нужно разбить цвета на компоненты RGB.

Затем рассчитайте разницу между началом и концом компонентов.

Наконец, рассчитайте процентную разницу и умножьте на начальный цвет каждого компонента, затем добавьте его к начальному цвету.

Предполагая, что вы можете получить значения RGB, это должно сделать это:

var diffRed = endColor.red - startColor.red;
var diffGreen = endColor.green - startColor.green;
var diffBlue = endColor.blue - startColor.blue;

diffRed = (diffRed * percentFade) + startColor.red;
diffGreen = (diffGreen * percentFade) + startColor.green;
diffBlue = (diffBlue * percentFade) + startColor.blue;

«Процентное затухание» - это плавающее десятичное число, показывающее, как далеко должно переходить значение «endColor». 1 будет полное затухание (таким образом создавая конечный цвет). 0 не будет исчезать (начальный цвет).

21
desau

Я использую эту функцию на основе ответа @desau:

 getGradientColor = function(start_color, end_color, percent) {
   // strip the leading # if it's there
   start_color = start_color.replace(/^\s*#|\s*$/g, '');
   end_color = end_color.replace(/^\s*#|\s*$/g, '');

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

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

   // get colors
   var start_red = parseInt(start_color.substr(0, 2), 16),
       start_green = parseInt(start_color.substr(2, 2), 16),
       start_blue = parseInt(start_color.substr(4, 2), 16);

   var end_red = parseInt(end_color.substr(0, 2), 16),
       end_green = parseInt(end_color.substr(2, 2), 16),
       end_blue = parseInt(end_color.substr(4, 2), 16);

   // calculate new color
   var diff_red = end_red - start_red;
   var diff_green = end_green - start_green;
   var diff_blue = end_blue - start_blue;

   diff_red = ( (diff_red * percent) + start_red ).toString(16).split('.')[0];
   diff_green = ( (diff_green * percent) + start_green ).toString(16).split('.')[0];
   diff_blue = ( (diff_blue * percent) + start_blue ).toString(16).split('.')[0];

   // ensure 2 digits by color
   if( diff_red.length == 1 ) diff_red = '0' + diff_red
   if( diff_green.length == 1 ) diff_green = '0' + diff_green
   if( diff_blue.length == 1 ) diff_blue = '0' + diff_blue

   return '#' + diff_red + diff_green + diff_blue;
 };

Пример:

getGradientColor('#FF0000', '#00FF00', 0.4);
=> "#996600"
11
drinor

ответ Десау это здорово. Вот это в JavaScript:

function hexToRgb(hex) {
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null;
}

function map(value, fromSource, toSource, fromTarget, toTarget) {
  return (value - fromSource) / (toSource - fromSource) * (toTarget - fromTarget) + fromTarget;
}

function getColour(startColour, endColour, min, max, value) {
  var startRGB = hexToRgb(startColour);
  var endRGB = hexToRgb(endColour);
  var percentFade = map(value, min, max, 0, 1);

  var diffRed = endRGB.r - startRGB.r;
  var diffGreen = endRGB.g - startRGB.g;
  var diffBlue = endRGB.b - startRGB.b;

  diffRed = (diffRed * percentFade) + startRGB.r;
  diffGreen = (diffGreen * percentFade) + startRGB.g;
  diffBlue = (diffBlue * percentFade) + startRGB.b;

  var result = "rgb(" + Math.round(diffRed) + ", " + Math.round(diffGreen) + ", " + Math.round(diffBlue) + ")";
  return result;
}

function changeBackgroundColour() {
  var count = 0;
  window.setInterval(function() {
    count = (count + 1) % 200;

    var newColour = getColour("#00FF00", "#FF0000", 0, 200, count);

    document.body.style.backgroundColor = newColour;
  }, 20);
}

changeBackgroundColour();

4
Fidel

Библиотека xolor имеет функцию градиента. Это создаст массив с 8 цветами в градиенте от начального цвета до конечного цвета:

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))
}  

Подробнее на github: https://github.com/fresheneesz/xolor

2
B T

Не такой мощный, но в большинстве случаев работает, и вам не нужно включать какие-либо другие библиотеки, кроме jQuery для следующего кода: 

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");

Это должно сделать div, который содержит радугу. Смотрите http://jsfiddle.net/rootandy/54rV7/

1
r00tandy

Мне нужно было создать достаточно большой массив вариантов цвета для неизвестного набора динамических элементов, но мне нужно было, чтобы каждый элемент увеличивал свой путь через начальный цвет и конечный цвет. Этот тип придерживается подхода «процентного затухания», за исключением того, что мне было трудно следовать этой логике. Вот как я подошел к нему, используя входные данные двух значений цвета RGB и вычисляя количество элементов на странице. 

Вот ссылка на кодовый блок , которая демонстрирует концепцию.

Ниже приведен фрагмент кода проблемы.

    <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>
1
theHaymaker

Базовый Javascript - Градиент фона

Вот готовая функция, чтобы установить фон элемента, чтобы быть градиентом

Использование CSS

Element.prototype.setGradient = function( from, to, vertical ){
   this.style.background = 'linear-gradient(to '+(vertical ? 'top' : 'left')+', '+from+', '+to+' 100%)';
}

И использование:

document.querySelector('.mydiv').setGradient('red','green');

Это было проверено работа с Chrome, я постараюсь обновить для других браузеров

Использование холста

Самая основная горизонталь будет:

Element.prototype.setGradient = function( fromColor, toColor ){

    var canvas = document.createElement('canvas');
    var ctx    = canvas.getContext('2d');
    var b      = this.getBoundingClientRect();
    var grd    = ctx.createLinearGradient(0, 0, b.width, 0);

    canvas.width = b.width;
    canvas.height = b.height;

    grd.addColorStop(0, fromColor);
    grd.addColorStop(1, toColor);

    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, b.width, b.height);

    this.style.backgroundImage = 'url('+canvas.toDataURL()+')';
}

И использование:

document.querySelector('.mydiv').setGradient('red','green');

A Fiddle: https://jsfiddle.net/jch39bey/

-

Добавление вертикального градиента

Простой флаг для установки вертикали

Element.prototype.setGradient = function( fromColor, toColor, vertical ){

    var canvas = document.createElement('canvas');
    var ctx    = canvas.getContext('2d');
    var b      = this.getBoundingClientRect();
    var grd    = ctx.createLinearGradient(0, 0, vertical ? 0 : b.width, vertical ? b.height : 0);

    canvas.width = b.width;
    canvas.height = b.height;

    grd.addColorStop(0, fromColor);
    grd.addColorStop(1, toColor);

    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, b.width, b.height);

    this.style.backgroundImage = 'url('+canvas.toDataURL()+')';
}

И использование:

document.querySelector('.mydiv').setGradient('red','green',true);
0
levi

Вы можете получить список элементов. Я не знаком с jQuery, но prototypejs имеет Element.childElements (), который будет возвращать массив. Как только вы узнаете длину массива, вы можете определить, насколько сильно нужно менять компоненты пикселя для каждого шага. Некоторые из следующего кода, который я не тестировал в той форме, в которой я их представляю, но, надеюсь, должны дать вам представление.

function hex (c) {
  var s = "0123456789abcdef";
  var i = parseInt (c);
  if (i == 0 || isNaN (c))
    return "00";
  i = Math.round (Math.min (Math.max (0, i), 255));
  return s.charAt ((i - i % 16) / 16) + s.charAt (i % 16);
}

/* Convert an RGB triplet to a hex string */
function convertToHex (rgb) {
  return hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}

/* Remove '#' in color hex string */
function trim (s) { return (s.charAt(0) == '#') ? s.substring(1, 7) : s }

/* Convert a hex string to an RGB triplet */
function convertToRGB (hex) {
  var color[];
  color[0] = parseInt ((trim(hex)).substring (0, 2), 16);
  color[1] = parseInt ((trim(hex)).substring (2, 4), 16);
  color[2] = parseInt ((trim(hex)).substring (4, 6), 16);
}


/* The start of your code. */
var start = convertToRGB ('#000000');    /* The beginning of your gradient */
var end   = convertToRGB ('#ffffff');    /* The end of your gradient */
var arr = $('.gradientList').childElements();
var len = arr.length();                  /* The number of colors to compute */
var alpha = 0.5;                         /* Alpha blending amount */

for (i = 0; i < len; i++) {
    var c = [];

    c[0] = start[0] * alpha + (1 - alpha) * end[0];
    c[1] = start[1] * alpha + (1 - alpha) * end[1];
    c[2] = start[2] * alpha + (1 - alpha) * end[2];

    /* Set the background color of this element */
    arr[i].setStyle ({ 'background-color': convertToHex (c) });
}
0
bratsche