如何操纵颜色以提供实时发光效果?

时间:2011-12-29 00:37:05

标签: delphi math colors delphi-7

我试图制作一个按钮,当鼠标指向它时会发光。后台必须有一个计时器来控制这些颜色的平滑淡入淡出。它不会从一种颜色跳到另一种颜色,它逐渐淡化为下一种颜色。

现在我的问题是,当它淡化回常规颜色时,它不会锁定到它的最终颜色。事实上,它一直从光明跳到黑暗。

这是我的自定义按钮,我不打算发布代码,但是这个代码可以放在任何带有鼠标进入/退出事件和颜色属性的按钮上。

它通过设置变量FMenuDestColor来工作。 ExtractColor根据颜色获取RGB值。计时器比较当前颜色和目标颜色之间的每个RGB通道。然后计时器修改当前颜色以淡入下一个颜色。这些计算在一个名为CalcColorFade的函数中完成 - 每个通道运行3次。

procedure ExtractColor(const Color: TColor; var R, G, B: Byte);
begin
  R:= GetRValue(Color);
  G:= GetGValue(Color);
  B:= GetBValue(Color);
end;

function CalcColorFade(const C1, C2: Byte): Byte;
const
  RGB_MULT = 1.2;
  RGB_SENS = 5;
begin
  if C1 <> C2 then begin    
    if (C1 >= C2 - RGB_SENS) and (C1 <= C2 + RGB_SENS) then
      Result:= C2
    else
      if C1 > C2 then
        Result:= EnsureRange(Trunc(C1 / RGB_MULT), 0, 255)
      else
        Result:= EnsureRange(Trunc(C1 * RGB_MULT), 0, 255);
  end else begin
    Result:= C2;
  end;
end;

procedure TfrmMain.tmrMenuGlowTimer(Sender: TObject);
var
  R1, G1, B1: Byte;
  R2, G2, B2: Byte;
  R3, G3, B3: Byte;
begin
  if MenuButton.Color <> FMenuDestColor then begin
    ExtractColor(MenuButton.Color, R1, G1, B1);
    ExtractColor(FMenuDestColor, R2, G2, B2);
    R3:= CalcColorFade(R1, R2);
    G3:= CalcColorFade(G1, G2);
    B3:= CalcColorFade(B1, B2);
    MenuButton.Color:= RGB(R3, G3, B3);
  end;
end;

procedure TfrmMain.MenuButtonMouseEnter(Sender: TObject);
begin
  FMenuDestColor:= clBlue;
end;

procedure TfrmMain.MenuButtonMouseLeave(Sender: TObject);
begin
  FMenuDestColor:= clNavy;
end;

将鼠标指向它,它将淡入下一种颜色。但是把鼠标从它上面移开,它有点不会锁定在原来的颜色位置 - 它在光明与黑暗之间来回摇晃。

我假设必须有一个更清洁的方法来完成我正在做的事情,我也对这些建议持开放态度。

计时器的间隔为70,常数为1.2,当改为1.1时,它的工作正常。所以要把它改成1.2就搞砸了。

2 个答案:

答案 0 :(得分:4)

为什么不切换到HSB / HSV模式?

然后你可以设置你的Hue(0-359),并控制饱和度,亮度和alpha。

后三者中的每一部都为您提供滚动发光效果的选项。

答案 1 :(得分:1)

通过将另一个常量RGB_SENS调整为7来解决问题。

所以看起来RGB_MULT越高,我就越高RGB_SENS

首先获取控件的当前颜色,然后获取目标颜色,将每个颜色分成RGB通道,然后对于每个通道,它执行此功能以获取“新”RGB值...

function DoCalc(const Curr, Dest: Byte): Byte;
const
  RGB_MULT = 1.2; //How much color change per step
  RGB_SENS = 10;  //Distance from dest +/- until "locked" into dest
begin
  if Curr <> Dest then begin
    if (Curr >= Dest - RGB_SENS) and (Curr <= Dest + RGB_SENS) then begin
      Result:= Dest; //Lock color into destination (sensitivity)
    end else begin
      if Curr > Dest then begin //Needs to go down
        Result:= EnsureRange(Trunc(Curr / RGB_MULT), 0, 255);
      end else begin            //Needs to go up
        Result:= EnsureRange(Trunc(Curr * RGB_MULT), 0, 255);
      end;
    end;
  end else begin
    Result:= Dest; //Just return the dest color, no change
  end;
end;

之前,RGB_MULT曾经设置为1.1,效果很好。但当我把它增加到1.2时,就是我的问题开始的时候。那时,RGB_SENS设置为5RGB_SENS确定目标颜色的距离,直到颜色应“锁定”到位。显然,1.2导致它永远不会落在这个范围内。将RGB_SENS扩展为7(现在为10)后,效果正常。