2010-06-20 271 views
36

使用帶或不帶Jquery的javascript,我需要根據開始和結束顏色創建顏色漸變。這是可能的編程方式嗎?Javascript顏色漸變

最終顏色只會是開始顏色的陰影,它是無序列表,我無法控制li項目的數量。我正在尋找一種解決方案,使我可以選擇開始和結束顏色,將十六進制值轉換爲RGB,以便在代碼中進行操作。開始的RGB值會根據項目數計算的步長值增加。

因此,如果列表中有8個項目,那麼它需要以8個步驟增加單獨的紅綠藍值以實現最終顏色。有沒有更好的方法來做到這一點,如果是的話,我可以在哪裏找到一些示例代碼?

+1

你描述的是我會做的方式:只需做起點和終點之間的線性插值爲三個顏色分量。 – Pointy 2010-06-20 18:37:43

+2

請注意,有不同類型的漸變:如果您要製作經過紅色 - >黃色 - >綠色 - >藍色的漸變,您可能需要獲取HSL值而不是RGB值。 – vaab 2012-11-14 08:46:32

回答

20

是的,絕對。

我在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; 

的「percentFade」是一個浮動的小數,表示多遠消失在「ENDCOLOR」。 1將會完全消失(從而創建最終顏色)。 0將不會褪色(起始顏色)。

+1

第二組賦值是新顏色集合 – alxndr 2012-02-16 03:18:44

0

您可以檢索元素列表。我不熟悉jQuery,但prototypejs有Element.childElements(),它將返回一個數組。一旦知道了陣列的長度,就可以確定爲每個步驟更改像素分量的數量。下面的一些代碼我沒有用我正在演示的表單進行測試,但它應該有希望給你一個想法。

function hex (c) { 
    var s = "abcdef"; 
    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) }); 
} 
+2

考慮用簡單的' .toString(16)'代替'hex'函數。 – haylem 2010-10-08 17:10:52

+1

這裏有很多錯誤。例如convertToRGB並不實際返回任何東西:) – 2011-10-26 22:57:43

67

我創建了一個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, 

歡迎您來看看圖書館的源代碼。 :)

+3

完美!這正是我所期待的。謝謝 – 2012-09-19 07:41:34

+0

這是一個非常有用的腳本,很好的工作。 – 2012-11-27 12:49:55

+1

謝謝,非常有幫助。將其用於即將在伊朗舉行的選舉。 ;) – pp19dd 2013-05-15 17:17:29

1

不是這樣強大,但在大多數情況下工作,你不必包括除了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/

10

我使用基於@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" 
23

正確的函數生成的顏色陣!

function hex (c) { 
 
    var s = "abcdef"; 
 
    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){ 
 

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

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

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

 
\t //Alpha blending amount 
 
\t var alpha = 0.0; 
 

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

 
\t \t saida.push(convertToHex (c)); 
 
\t \t 
 
\t } 
 
\t 
 
\t return saida; 
 
\t 
 
} 
 

 
// 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>") 
 
    
 
} 
 
\t
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="result_show"></div>

+1

你是一個現代的畢加索。這是DOPE! – lol 2015-11-14 06:21:12

+0

正是我所期待的。謝謝。 – DolceVita 2017-08-25 09:04:33

1

我需要創建的顏色選擇一個足夠大的陣列未知組動態的元素,但我需要每一個元素來增加通過開始彩色了路,終點顏色。這種方式遵循「百分比淡化」的方法,除了我遵循邏輯之後的困難時間。這就是我使用兩個rgb顏色值的輸入並計算頁面上元素的數量的方法。

這是一個link to a codepen,它演示了這個概念。

下面是問題的代碼片段。

<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

xolor library具有漸變功能。這將創建與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

0

desau's answer是很大的。這是在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();