2011-12-29 7 views
6

Sto provando a creare un pulsante che si illumina quando viene puntato il mouse su di esso. Ci deve essere un timer in sottofondo per controllare una dissolvenza fluida di questi colori. Non salta da un colore all'altro, gradualmente sfuma al colore successivo.Come manipolare i colori per dare un effetto luminoso in tempo reale?

Ora il mio problema è che quando si dissolve nuovamente al suo colore normale, non si blocca nel colore finale. Infatti, continua a saltare dalla luce al buio.

Questo è un mio pulsante personalizzato, di cui non ho intenzione di pubblicare il codice, ma questo codice può essere inserito in qualsiasi cosa con un evento di input/exit del mouse e una proprietà di colore.

Funziona impostando una variabile FMenuDestColor. ExtractColor ottiene i valori RGB in base a un colore. Il timer confronta ogni canale RGB tra il colore corrente e il colore di destinazione. Quindi il timer modifica il colore corrente da sfumare al successivo. Questi calcoli vengono eseguiti in una funzione denominata CalcColorFade, eseguita 3 volte per ciascun canale.

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; 

Puntare il mouse su di esso e si dissolverà al colore successivo. Ma togliti il ​​mouse e non si blocca in posizione con il suo colore originale - si muove avanti e indietro tra la luce e il buio.

Suppongo che ci debba essere un approccio più pulito per realizzare ciò che sto facendo, e sono aperto anche a questi suggerimenti.

L'intervallo del timer è a 70 e la costante di 1,2, se modificata a 1,1, funziona perfettamente. Quindi qualcosa su come cambiarlo in 1.2 che lo ha incasinato.

+1

Penso che troverai il tuo codice più facile da leggere se prendi lo stesso codice di gestione R, G e B e lo consideri in una procedura da solo e lo chiami tre volte: passando in 'R1' e' R2 'alla prima esecuzione,' G1' e 'G2' alla seconda esecuzione, ecc. – sarnold

+0

@sarnold Un buon consiglio che avrei comunque finito, anche se non correlato alla domanda. –

+0

Abbastanza vero, motivo per cui l'ho lasciato come commento: non riesco a individuare il problema che stai provando a risolvere. Dando solo il suggerimento che sarebbe più facile risolverlo solo una volta anziché tre volte se è in quei blocchi ... :) – sarnold

risposta

1

Il problema è stato risolto regolando l'altra costante RGB_SENS a 7.

Quindi sembra che più alto vado con RGB_MULT, più alto devo prendere RGB_SENS.

Quello che succede è che prima ottiene il colore corrente del controllo, quindi ottiene il colore di destinazione, divide ciascuno di quei colori in canali RGB, quindi per ciascuno di quei canali, fa questa funzione per ottenere il "nuovo" RGB valore ...

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; 

Prima, RGB_MULT usato per essere fissato a 1.1, che ha lavorato bene. Ma quando l'ho aumentato a 1.2, questo è il momento in cui è iniziato il mio problema. A quel tempo, RGB_SENS era impostato su 5. RGB_SENS determina la distanza dal colore di destinazione fino a quando il colore non deve "bloccare" in posizione. Evidentemente, lo 1.2 non ha mai toccato terra in questo intervallo. Dopo l'espansione di RGB_SENS a 7 (e ora 10), funziona correttamente.

+0

La cosa buffa è che ho scritto la matematica per questa cosa, ma non riesco a spiegare a parole come funzioni realmente: PI tende a leggere/parlare in linguaggio di codice, non riesco a tradurre il codice in inglese semplice ... –

+0

Questo è totalmente comune. Non cercare di forzarlo nel linguaggio, a volte può rovinare la bellezza della logica. : P –

4

Perché non passare semplicemente alla modalità HSB/HSV?

Quindi è possibile impostare la tonalità (0-359) e controllare la saturazione, la luminosità e l'alfa.

Ciascuno di questi ultimi tre offre opzioni per un effetto bagliore a rotazione.

+0

Fresco, ma include la fusione da un colore a un altro, ad esempio da blu a verde? Il mio obiettivo è passare da un colore a un altro, non solo un po 'più chiaro o più scuro. –

+0

Se si passa attraverso la tonalità, i colori cambieranno ma mantengono intatta la luminosità e la saturazione relative. – sarnold

+0

Capito, ma come funzionerebbe per passare da un qualsiasi colore a qualsiasi altro colore? Da rosso a verde, da blu a viola, da ciano a nero, da bianco a blu cielo, qualsiasi 2 colori specificati, non vedo come funzionerebbe. –

Problemi correlati