Как манипулировать цветами для создания эффекта свечения в реальном времени?

Я пытаюсь сделать кнопку, которая светится, когда на нее наводят мышь. В фоновом режиме должен быть таймер для управления плавным переходом от одного цвета к другому. Она не перескакивает с одного цвета на другой, а постепенно переходит на следующий цвет.

Теперь моя проблема в том, что когда он возвращается к своему обычному цвету, он не фиксируется на своем конечном цвете. Фактически, он продолжает прыгать от светлого к темному.

Это моя пользовательская кнопка, код которой я не собираюсь публиковать, но этот код может быть размещен на чем угодно с событием входа/выхода мыши и свойством цвета.

Он работает путем установки переменной 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 все испортилось.

6
задан Jerry Dodge 29 December 2011 в 01:16
поделиться