JavaScript颜色渐变

66

使用JavaScript和jQuery,我需要根据起始和结束颜色创建一个渐变色。是否可以通过编程实现此功能?

结束颜色将始终是起始颜色的较暗色调,并且它是用于无序列表的,我无法控制li项的数量。我正在寻找一种解决方案,允许我选择起始和结束颜色,将十六进制值转换为RGB,以便可以在代码中进行操作。起始RGB值通过基于项目数量计算的步骤值递增。

因此,如果列表有8个项,则需要将Red Green Blue值在8个步骤中递增以实现最终颜色。是否有更好的方法来完成此操作,如果有,可以在哪里找到一些示例代码?


1
你描述的方法是我所采取的方式:对于每个三个颜色成分,只需在起点和终点之间进行线性插值即可。 - Pointy
2
请注意,渐变有不同类型:如果您想制作一个经过红色->黄色->绿色->蓝色的渐变,您可能需要获取HSL值而不是RGB值。 - vaab
15个回答

110

我创建了一个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
谢谢,非常有帮助。我会在即将到来的伊朗选举中使用它。;) - pp19dd
3
你的图书馆真的很棒! - DontVoteMeDown
1
谢谢Anomal :) 找到了我所寻找的确切内容。 - ABHILASH SB
要尝试这个示例,请使用:https://codepen.io/eqvis/pen/ExdLdBZ - Mayra Delgado

54
这里有一个函数可以生成一个颜色数组!

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

// Usage example
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>


非常感谢,您提供了我所需要的准确翻译。 - DolceVita
1
你能用多种颜色实现这个效果吗?我尝试过了但是没成功。https://stackoverflow.com/questions/51659031/how-can-i-make-a-multi-color-gradient-scale?noredirect=1#comment90282709_51659031 - FussinHussin
@FussinHussin 是的,我创建了另一个函数,基本上使用从 generateColor 生成的两个数组,其中我传入了起始、中间和结束颜色。然后将这些数组组合起来,形成一个三色渐变。 - Reed
一些小问题:[代码库良好] //计算的颜色数量 var len = colorCount - 1; //最后一个颜色... //Alpha混合量 var alpha = 0.0; var saida = []; // 最后一个颜色 saida.push(colorEnd.toUpperCase()); ... saida.reverse(); 返回saida; - mshaffer

31

是的,绝对可以。

我用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
1
只是提供信息,不需要括号。 - vanowm

20

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

6

desau的答案 很棒。以下是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

chroma.js:

chroma.scale(['#fafa6e','#2A4858']).mode('lch').colors(6)

4

有一个可以创建颜色渐变的JavaScript库:

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


4
基于@drinor的答案- 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;
}

例子:

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

=> "#996600"

3

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


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/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接