颜色从蓝色跳到中提琴

Color jumps from Blue to violette

本文关键字:中提琴 蓝色 颜色      更新时间:2023-09-26

我正在实现一个彩色屏幕保护程序。有一个颜色范围和一个滑块。

颜色为(HSB)。有6种颜色。

blue (230, S,B)
green (130, S,B)
yellow (55, S,B)
orange (40, S,B)
red (0(or 360), S,B)
violette (315, S,B)

滑块值从0到14.9

blue 0 - 2.9 green
green 3 - 5.9 yellow
yellow 6 - 8.9 orange
orange 9 - 11.9 red
red 12 - 14.9 violette

如果使用滑块值,并且旧滑块值和新滑块值之间的差小于2.9,则实际色调将改变0.5。

现在,如果差距大于2.9,就必须有一个跳跃。在滑块值小于12之前,此操作效果良好。值为12时,颜色从0变为360,我的代码不再工作。

// this works fine
if (lastSlide < 12) {
            // jump statement
            if (Math.abs(Math.round(top.fillColor.hue - value)) > 41){
                var fillColor = Math.round((Math.abs((value-top.fillColor.hue))/1.05) + Math.min(value, Math.round(top.fillColor.hue)));
                if (fillColor < 0) fillColor = adjustValue(fillColor);
                top.fillColor.hue = fillColor;
            }
            else if (Math.abs(Math.round(top.fillColor.hue - value)) < 41 && top.counter_dsg < 20){
                top.fillColor.hue-= 0.5; 
                top.counter_dsg+=0.5;
            }
            else if (Math.abs(Math.round(top.fillColor.hue - setValue())) < 41 && top.counter_dsg > 19){
                top.fillColor.hue+= 0.5; 
                top.counter_dsg+=0.5;
            }
            else top.fillColor.hue -= 0.5;
            if (top.counter_dsg > 39) top.counter_dsg = 0;
        }
// this not
else {
    // jump statement
    if (Math.abs(Math.round(top.fillColor.hue - value)) > 41){
        var fillColor = Math.round((Math.abs((value-top.fillColor.hue))/1.05) - Math.min(value, Math.round(top.fillColor.hue)));
        if (fillColor < 0) fillColor = adjustValue(fillColor);
        top.fillColor.hue = fillColor;
    }
    else if (Math.abs(Math.round(value - top.fillColor.hue)) < 41 && top.counter_dsg < 20){
        top.fillColor.hue-= 0.5;
        top.counter_dsg+=0.5;
    }
    else if (Math.abs(Math.round(value - top.fillColor.hue)) < 41 && top.counter_dsg > 19){
        top.fillColor.hue+= 0.5; 
        top.counter_dsg+=0.5;
    }
    else top.fillColor.hue -= 0.5;
    if (top.counter_dsg > 39) top.counter_dsg = 0;
}

编辑:

好吧,假设屏幕上有一个画布,我想用滑块来改变画布的颜色。如果未使用滑块,则画布的实际颜色是摆动的(+10hue,-10hue)。

示例

画布的颜色是蓝色(230色调,s,b),我没有使用滑块,所以画布的颜色通过添加0.5来改变(计数器计数:20次),之后0.5将从颜色中减去,直到计数器达到40,然后计数器设置为0。因此,颜色在(220色调,s,b)和(240色调,s、b)之间摆动

现在,如果我使用滑块(slidersteps=0.1),颜色将更改为新值。

在示例中我使用滑块,滑块值为2.9,然后颜色通过减去0.5色调变为绿色。台阶看起来像(230h,s,b),(229.5h,s、b),…,(130h,s和b)。如果达到(130h、s和b,颜色开始摆动。

此外,如果新的滑块值比旧的大得多,则必须有从旧颜色到新颜色的更快变化。

示例滑块值=11.9,最后一个滑块值=2.9,两者之间的差值为9。因此,如果差值大于2.9,我想从绿色到红色走得更快。所以我决定用这个公式(旧值-新值)/1.05+Min[旧值,新值]得到下一个值步骤看起来像(130h,s,b),(123h,s、b),。。。,(0h,s,b)

这在从红色变为紫色之前一直很好,因为红色的值是0,下一个值是360,直到325紫色。所以我很困惑如何用这个值改变来获得与上面相同的步骤

第2版:

1.) yes its the actual hue
2.) my fault...it's always setValue() - i have declare it above in this ways value = setValue() to use it once time and didn't change it everywhere 
3.) value = setValue() -> the Hue calculated by the slider
4.) yes
5.) yes

要在最短路径上从一种颜色到另一种颜色Joel的答案很好,我再好不过了。所以我做了另一种方法,尽可能地接近您已经拥有的代码,因为您说第一部分工作得很好。

在函数setValue()中,beforelast行是else c = 360 - m * 15;。更改为:

else c = m * -15;

现在,当sliderValue从12变为15时,函数将返回从0到-45的负色调。这样,您就可以删除从0到315的"跳跃",并在sliderValue增加(和相反)时获得连续递减的值。由于现在值可以是<每次为画布设置值时,0都使用adjustValue()adjustValue()内部检查< 0,因此不需要额外检查)。然后你发布的所有代码都可能是这样的:

var cur = top.fillColor.hue;
if (cur > 300) cur -= 360;
var dif = cur - setValue();
if (Math.abs(dif) > 41) cur -= Math.round(dif / 1.05);
else {
    cur += top.counter_dsg < 20 ? -0.5 : 0.5; 
    top.counter_dsg += 0.5
}
if (top.counter_dsg > 39) top.counter_dsg = 0;
top.fillColor.hue = adjustValue(cur);

我希望我的答案是正确的,但我真的不确定你想做什么。如果我理解,你想在颜色变化上有一些过渡效果,对吧?

我提出了一种完全不同的方法,更"数学",更流畅。假设你想在1秒内实现颜色转换,不管从旧颜色到新颜色的跳跃有多大。你只需要确定一个"过渡向量",这将是最短的可能:如果比例从0到360,向量是:(540+新-旧)%360-180。

为什么?"天真"的矢量只是(新的-旧的)。通过加360,然后模360,我们确保我们有一个正数。通过在取模之前加180(540=180+360),然后在取模之后去掉180,我们确保我们有一个范围为[-180,180]=>的数字,这就是我们想要得到的最短路径。

例如,使用以下公式:

  • 如果旧=5,新=10=>矢量为+5
  • 如果旧=350,则新=10=>矢量为+20
  • 如果旧=350,新=340=>矢量为-10

然后,一旦你计算了这个向量,你只需要将它应用于每个时间帧的颜色值,乘以时间因子。例如:

var v = (540 + newColor - oldColor) % 360 - 180;
var currentColor = oldColor;
var delta = 200; // milliseconds
var timeElapsed = 0;
var timeFrame = 1000; // 1s
var hInt = setInterval(function() {
    if (timeElapsed >= timeFrame) {
       clearInterval(hInt);
       currentColor = newColor;
    } else {
       timeElapsed += delta;
       currentColor += v * delta / timeFrame;
    }
}, delta);

随着时间的推移,"currentColor"将为您提供正确的颜色。