Как манипулировать цветами, чтобы получить эффект свечения в реальном времени? - PullRequest
6 голосов
/ 29 декабря 2011

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

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

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

Работает, устанавливая переменную 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 ]

4 голосов
/ 29 декабря 2011

Почему бы просто не переключиться в режим HSB / HSV?

Затем вы можете установить свой оттенок (0-359) и управлять насыщенностью, яркостью и альфа-каналом.

Каждый из трех последних вариантов дает вам возможность получить эффект свечения.

1 голос
/ 29 декабря 2011

Проблема была решена путем настройки другой константы 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 определяет, как далеко от цвета Destination до цвета должен «зафиксироваться» на месте. Очевидно, 1.2 заставил его никогда не приземлиться в этом диапазоне. После расширения RGB_SENS до 7 (а теперь и 10) все работает нормально.

...