【问题标题】:Color jumps from Blue to violette颜色从蓝色跳到紫罗兰色
【发布时间】:2014-12-31 13:24:53
【问题描述】:

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

颜色为 (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 hue, s,b) 和 (240hue, 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 紫色。所以我很困惑如何通过这个值更改来获得与上面相同的步骤

EDIT2:

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

【问题讨论】:

  • 我仍然不知道您要做什么。 :P 很多神奇的数字都可以使用一些不神奇的东西。暂时忘记数字,更清楚地解释目标。 (更好的是,发布一个更完整的示例作为小提琴或堆栈 sn-p。)
  • 为了得到令人满意的答案,我需要澄清一下。 1) top.fillColor.hue 是实际画布颜色的色调吗? 2) 为什么你有时使用value 有时使用setValue()? 3) value 是新色调吗? 4) setValue()HERE 的函数吗? 5) adjustValue()HERE 的函数吗?请在问题中编辑您的答案。

标签: javascript math colors


【解决方案1】:

我希望我能正确回答,但我不确定你要做什么。如果我理解,您希望在颜色变化时产生一些过渡效果,对吧?

我提出了一种完全不同的方法,更“数学”,更流畅。假设您希望在 1 秒内实现颜色过渡,无论从旧颜色到新颜色的跳跃有多大。您只需要确定一个“过渡向量”,这将是最短的:如果比例从 0 变为 360,则向量为:(540 + new - old) % 360 - 180。

为什么? “天真的”向量只是(新旧)。通过添加 360 然后模 360,我们确保我们有一个正数。通过在模前添加 180 (540=180+360),然后在模后删除 180,我们确保我们有一个范围为 [-180, 180] => 的数字,这是我们想要获得的最短路径。

例如,用这个公式:

  • 如果 old=5,new=10 => 向量为 +5
  • 如果旧=350,新=10 =>向量是+20
  • 如果 old=350, new=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”会随着时间的推移为您提供正确的颜色。

【讨论】:

    【解决方案2】:

    要在最短路径上从一种颜色变为另一种颜色 Joel 的回答很好,我无法做得更好。因此,我采用另一种方法尽可能接近您已经拥有的代码,因为您说第一部分工作正常。

    在函数setValue() 的最后一行是else c = 360 - m * 15;。将其更改为:

    else c = m * -15;
    

    现在当 sliderValue 从 12 变为 15 时,该函数返回从 0 到 -45 的负色调。这样,您可以从 0 到 315 移除“跳跃”,并在 sliderValue 增加(反之亦然)时获得不断减小的值。由于现在值可以 adjustValue()(adjustValue() 内部检查 &lt; 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-05
      • 2014-11-03
      • 2011-04-08
      • 1970-01-01
      • 2021-03-27
      • 2022-10-17
      • 2020-06-10
      • 2021-01-12
      相关资源
      最近更新 更多