我试图制作一个按钮,当鼠标指向它时会发光。后台必须有一个计时器来控制这些颜色的平滑淡入淡出。它不会从一种颜色跳到另一种颜色,它逐渐淡化为下一种颜色。
现在我的问题是,当它淡化回常规颜色时,它不会锁定到它的最终颜色。事实上,它一直从光明跳到黑暗。
这是我的自定义按钮,我不打算发布代码,但是这个代码可以放在任何带有鼠标进入/退出事件和颜色属性的按钮上。
它通过设置变量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就搞砸了。
答案 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
设置为5
。 RGB_SENS
确定目标颜色的距离,直到颜色应“锁定”到位。显然,1.2
导致它永远不会落在这个范围内。将RGB_SENS
扩展为7
(现在为10
)后,效果正常。