2

我很抱歉标题不好(如果你愿意,可以编辑),但我不知道如何提出这个请求。我附上了一张来自 Photoshop 的图片,它可以更好地说明事情。

请求本身非常简单:您有一个从 10.0 到 0.0 的数字范围。10 代表颜色#00ff00(深绿色),0.0 代表颜色#ff0000(深红色)。

现在,当您交出数字 10.0 时,它将输出 #00ff00。当你给它 8.2 之类的东西时,它会输出类似 #00cc33 的东西,这样你就有一个一直向下的浮动渐变,但总是从 #00ff00 浮动到橙色 #ff9900 到 #ff0000 (中间的橙色也可以省略)。

这就是我想要的

4

5 回答 5

4

一种方法是将颜色想象成圆的一部分,然后使用Math.cosor Math.sin

function toColour(x) {
    var pad = function (x) {
        x = x.toString(16);
        if (x.length === 1) {
            return '0' + x;
        }
        return x;
    }, r, g, b;
    r = ~~(255 * Math.cos(Math.PI * x / 20)); // cos(0) = 1, cos(π/2) = 0
    g = ~~(255 * Math.sin(Math.PI * x / 20)); // sin(0) = 0, sin(π/2) = 1
    b = 0;
    return '#' + pad(r) + pad(g) + pad(b);
}

// test the gradient produced
for (var i = 0; i <= 10; ++i) {
    document.body.appendChild(
        document.createElement('div')
    ).setAttribute('style', 'width: 400px;height: 5px;background: '+toColour(i)+';');
}

请参阅此小提琴以获取测试结果(感谢MikeM

于 2013-01-27T20:10:51.807 回答
3

只是为了好玩:

function toHex( n ) {
    var r = 255 - ( n / 10 * 255 | 0 ); 
        g = n / 10 * 255 | 0;  

    return '#' + 
        ( r ? ( r = r.toString(16), r.length == 2 ? r : '0' + r ) : '00' ) +
        ( g ? ( g = g.toString(16), g.length == 2 ? g : '0' + g ) : '00' ) + '00'
}

在这里看到它(它的价值):http: //jsfiddle.net/xD6Uf/

更新

受 Samuel Edwin Ward 使用 HSL 的启发,以下函数改编hslToRgb自 Brian Grinstead 的 MIT Licensed tinycolor.js

注意:此功能不打算成为成品或代表良好实践,它只是概念证明。没有边界检查,对可读性的让步也很少。

n是一个从 0 到 10 的值startmiddleend是一个从 0 到 360 的色调值。
请参阅Mother-effing hsl来选择要试验的色调、饱和度和亮度值。

function toHex( n ) {
    var r, g, b, p, q,
        start = 0,          // 0 - 360 (red 0)
        middle = 36,        // 0 - 360 (orange 36, use 0 or null for no middle)
        end = 120,          // 0 - 360 (green 120)
        saturation = 1,     // 0 - 1
        lightness = 0.5,    // 0 - 1
        hue = ( middle ?
            n > 5 ? ( n -= 5, n / 5 * ( end - middle ) ) + middle :
                ( n / 5 * ( middle - start ) ) + start :
                    ( n / 10 * ( end - start ) ) + start ) / 360;

    function hue2hex( p, q, h ){
        if ( h < 0 ) h++;
        else if ( h > 1 ) h--;
        h = ( h < 1/6 ? p + ( q - p ) * 6 * h : h < 1/2 ? q :
            h < 2/3 ? p + ( q - p ) * ( 2/3 - h ) * 6 : p ) * 255 | 0;
        return h ? ( h = h.toString(16), h.length > 1 ? h : '0' + h ) : '00';
    }

    if ( saturation === 0 ) {
        n = lightness * 255 | 0;
        r = g = b = n ?
            ( n = n.toString(16), n.length > 1 ? n : '0' + n ) : '00'; 
    } else {
        q = lightness < 0.5 ? lightness * ( 1 + saturation ) :
            lightness + saturation - lightness * saturation;
        p = 2 * lightness - q;
        r = hue2hex( p, q, hue + 1/3 );
        g = hue2hex( p, q, hue );
        b = hue2hex( p, q, hue - 1/3 );
    }

    return '#' + r + g + b;
}

例子

toHex(0);    // "#ff0000"
toHex(5);    // "#ff9900"
toHex(10);   // "#00ff00"

jsfiddle

于 2013-01-27T19:56:38.107 回答
3

看起来您想在颜色之间进行插值。

您可以将颜色值设为数字并在它们之间进行插值,但我认为结果会很奇怪。

您可能希望将颜色从 RGB 转换为另一个颜色空间并缩放色调分量。HSL 将是一个不错的选择,因为 CSS3 支持在该空间中指定颜色。

颜色比例的图像

我将这两种方法的代码放在 jsfiddle 上

这些是重要的部分:

/* numeric interpolation */
for (var value = 0; value < 10; value += 10/40) {
    var color = (10-value)/10*(0xff0000-0xff00)+(0x00ff00),
        hex = Math.floor(color).toString(16);

    while (hex.length < 6) {
        hex = "0" + hex;
    }

    /* hex now holds the hex code */
  }

/* hue interpolation */

for (var value = 0; value < 10; value += 10/40) {
    var hue = value/10*120, /* red is 0; green is 120 */
        color = 'hsl(' + hue + ', 100%, 50%)';

    /* hsl now holds the hsl color specification */
}

如果您愿意,可以使用比我使用的简单线性公式(其中 x 是输入比例,y 是输出比例)更高级的方法来插值:

y = (x - minX) / (maxX - minX) * (maxY-minY) + minY
于 2013-01-27T20:02:38.750 回答
1

所以基本上你有一些带有两个变量的十六进制范围:

var startHex = "0x00ff00";
var endHex = "0xff0000"
int startInt = parseInt(startHex, 16);
int endInt = parseInt(endHex, 16);
int newInt = startInt + (endInt-startInt)/100 * floatValue; // floatValue is number between 10.0 and 0.0
var newHex = newDec.ToString(16);

我假设您打算在开始和结束之间进行 100 次增量。这可以做得更干净,但为了说明,我把它全部打破了。在实践中,我会用 1-2 行来写这个。

于 2013-01-27T19:50:10.013 回答
0

如果你想依赖浏览器的渲染引擎,你可以使用 HTML5 的 canvas 和createLinearGradient. 这种方法的一个优点是能够使用色标(尽管如果你真的想要也可以在数学上做到这一点)。

var canvas = document.createElement('canvas'),
    context = canvas.getContext('2d');

canvas.height = 100; canvas.width = 1;

var gradient = context.createLinearGradient(0,0,0,100);

// color stops
gradient.addColorStop(0, '#00ff00');
gradient.addColorStop(0.5, '#ff9900');
gradient.addColorStop(1, '#ff0000');

context.fillStyle = gradient;
context.fillRect(0,0,1,100);

var point = 10.0,
    colorData = context.getImageData(0, parseInt(point*canvas.height*.1, 10), 1, 1).data;

// rgba ( colorData[0], colorData[1], colorData[2], colorData[3] )

colorData[0]您可以在(红色)、colorData[1](蓝色)、 (绿色)中找到颜色的确切 rgba 坐标,colorData[2]然后轻松将它们转换为十六进制值。

如果您最终使用此解决方案,请设置point为 0 到 9.9 范围内的数字。

于 2013-01-27T20:13:21.340 回答