2009-04-02 11 views
7

Ich möchte eine Textbox in .NET "glühen" gelb, und dann "verblassen" zu weiß (im Grunde, indem Sie schrittweise die Helligkeit erhöhen). Ich denke, Stackoverflow macht das, nachdem Sie eine Antwort geschrieben haben. Ich weiß, dass die zunehmende Helligkeit nicht so einfach ist (es ist nicht nur das gleichmäßige Erhöhen/Verringern von RGB), aber ich bin mir nicht sicher, wie ich das machen soll.Fade eine Farbe zu weiß (zunehmende Helligkeit)

Perfekte Farbgenauigkeit spielt dabei keine Rolle. Ich benutze C#, obwohl VB Beispiele auch gut wären.

Bearbeiten: Dies ist für Winforms.

Antwort

8

Dies kann mehr als Sie benötigen, ist hier der Code für die Klasse I verwenden:

public class ControlColorAnimator 
{ 
    private const int INTERVAL = 100; 

    private readonly decimal _alphaIncrement; 
    private readonly decimal _blueIncrement; 
    private readonly Color _endColor; 
    private readonly decimal _greenIncrement; 
    private readonly int _iterations; 
    private readonly decimal _redIncrement; 
    private readonly Color _startColor; 

    private decimal _currentAlpha; 
    private decimal _currentBlueValue; 
    private decimal _currentGreenValue; 
    private decimal _currentRedValue; 

    private Timer _timer; 

    public ControlColorAnimator(TimeSpan duration, Color startColor, Color endColor) 
    { 
     _startColor = startColor; 
     _endColor = endColor; 
     resetColor(); 

     _iterations = duration.Milliseconds/INTERVAL; 
     _alphaIncrement = ((decimal) startColor.A - endColor.A)/_iterations; 
     _redIncrement = ((decimal) startColor.R - endColor.R)/_iterations; 
     _greenIncrement = ((decimal) startColor.G - endColor.G)/_iterations; 
     _blueIncrement = ((decimal) startColor.B - endColor.B)/_iterations; 
    } 

    public Color CurrentColor 
    { 
     get 
     { 
      int alpha = Convert.ToInt32(_currentAlpha); 
      int red = Convert.ToInt32(_currentRedValue); 
      int green = Convert.ToInt32(_currentGreenValue); 
      int blue = Convert.ToInt32(_currentBlueValue); 

      return Color.FromArgb(alpha, red, green, blue); 
     } 
    } 

    public event EventHandler<DataEventArgs<Color>> ColorChanged; 

    public void Go() 
    { 
     disposeOfTheTimer(); 
     OnColorChanged(_startColor); 

     resetColor(); 

     int currentIteration = 0; 
     _timer = new Timer(delegate 
      { 
       if (currentIteration++ >= _iterations) 
       { 
        Stop(); 
        return; 
       } 
       _currentAlpha -= _alphaIncrement; 
       _currentRedValue -= _redIncrement; 
       _currentGreenValue -= _greenIncrement; 
       _currentBlueValue -= _blueIncrement; 
       OnColorChanged(CurrentColor); 
      }, null, TimeSpan.FromMilliseconds(INTERVAL), TimeSpan.FromMilliseconds(INTERVAL)); 
    } 

    public void Stop() 
    { 
     disposeOfTheTimer(); 
     OnColorChanged(_endColor); 
    } 

    protected virtual void OnColorChanged(Color color) 
    { 
     if (ColorChanged == null) return; 
     ColorChanged(this, color); 
    } 

    private void disposeOfTheTimer() 
    { 
     Timer timer = _timer; 
     _timer = null; 

     if (timer != null) timer.Dispose(); 
    } 

    private void resetColor() 
    { 
     _currentAlpha = _startColor.A; 
     _currentRedValue = _startColor.R; 
     _currentGreenValue = _startColor.G; 
     _currentBlueValue = _startColor.B; 
    } 
} 

Dies verwendet DataEventArgs<T> (siehe unten)

/// <summary> 
/// Generic implementation of <see cref="EventArgs"/> that allows for a data element to be passed. 
/// </summary> 
/// <typeparam name="T">The type of data to contain.</typeparam> 
[DebuggerDisplay("{Data}")] 
public class DataEventArgs<T> : EventArgs 
{ 
    private T _data; 

    /// <summary> 
    /// Constructs a <see cref="DataEventArgs{T}"/>. 
    /// </summary> 
    /// <param name="data">The data to contain in the <see cref="DataEventArgs{T}"/></param> 
    [DebuggerHidden] 
    public DataEventArgs(T data) 
    { 
     _data = data; 
    } 

    /// <summary> 
    /// Gets the data for this <see cref="DataEventArgs{T}"/>. 
    /// </summary> 
    public virtual T Data 
    { 
     [DebuggerHidden] 
     get { return _data; } 
     [DebuggerHidden] 
     protected set { _data = value; } 
    } 

    [DebuggerHidden] 
    public static implicit operator DataEventArgs<T>(T data) 
    { 
     return new DataEventArgs<T>(data); 
    } 

    [DebuggerHidden] 
    public static implicit operator T(DataEventArgs<T> e) 
    { 
     return e.Data; 
    } 
} 

Verwendung in dem Formular wie folgt aus:

private ControlColorAnimator _animator; 

private void runColorLoop() 
{ 
    endCurrentAnimation(); 
    startNewAnimation(); 
} 

private void endCurrentAnimation() 
{ 
    ControlColorAnimator animator = _animator; 
    _animator = null; 
    if (animator != null) 
    { 
     animator.ColorChanged -= _animator_ColorChanged; 
     animator.Stop(); 
    } 
} 

private void startNewAnimation() 
{ 
    _animator = new ControlColorAnimator(TimeSpan.FromSeconds(.6), Color.Yellow, BackColor); 
    _animator.ColorChanged += _animator_ColorChanged; 
    _animator.Go(); 
} 

private void _animator_ColorChanged(object sender, DataEventArgs<Color> e) 
{ 
    invokeOnFormThread(delegate { setColor(e); }); 
} 

private void setColor(Color color) 
{ 
    // code to set color of the controls goes here 
} 

private void invokeOnFormThread(MethodInvoker method) 
{ 
    if (IsHandleCreated) 
     Invoke(method); 
    else 
     method(); 
} 
+0

Das ist sehr schlau, danke :) Ich habe es geändert (um einen Ausblenden-Parameter zu übergeben, also wenn die Animation endet, ist das Steuerelement ausgeblendet) und es meiner Basisklasse hinzugefügt, jetzt könnten alle meine geerbten Formulare möglicherweise setColor überschreiben und verwenden . Ich habe keinen eleganten Weg gefunden, ein Steuerelement an die Stelle der Animation zu stellen, anstatt es in setColor "hart zu codieren". Irgendwelche Ideen? –

+0

Habe es nicht versucht, aber vielleicht eine Erweiterungsmethode für das Steuerelement ... dann könnte man es so nennen "invokeOnFormThread (myControl.SetColor (e));" –

+0

Danke, wird untersucht.In der Zwischenzeit habe ich runColorLoop() modifiziert, so dass ich eine Farbe, eine Dauer, ein Steuerelement übergeben kann und wenn ich mich verstecken will, nachdem die Animation vorbei ist, kann ich das alles in meiner Basisklasse und jedem geerbten verwenden form kann base.runColorLoop (x, y, z, f) verwenden; –

0

Sie haben ursprünglich keine Technologie angegeben, als ich diese Antwort eingereicht habe, aber Sie würden dies mit jQuery tun.

UI/Effects/Highlight.

$("div").click(function() { 
     $(this).effect("highlight", {}, 3000); 
}); 
+0

er sagte "winforms" –

+0

Bah, anscheinend ist die Zukunft "Web-Apps" in "der Wolke" auf Ihrem "e-Begleiter". Also sollte er Webkit in seine Anwendung integrieren und die CSS-Effekte und Animationen verwenden, die er unterstützt! – JeeBee

+0

Ich fühle mich so retro :) –

2

Interpolieren Sie einfach zwischen den Farben basierend auf der Zeit.

Wenn Ihre orange Farbe (r1, g1, b1) ist und Sie zu einer anderen Farbe (r2, g2, b2) blenden möchten, lautet die Formel für lineare Interpolation (r1 + (r2-r1) * t, g1 + (g2-g1) · t, b1 + (b2-b1) · t), wobei t im Bereich von [0,0 1,0] liegt.

In Ihrem Beispiel ist Ihre erste Farbe wahrscheinlich etwas (255,200,0) und Ihre zweite Farbe wäre (255,255,255).

Wenn Sie glattere Übergänge wünschen, können Sie nach verschiedenen Interpolationsmethoden suchen.

0

Wenn Sie es schnell und reibungslos machen möchten, werfen Sie einen Blick auf die ColorMatrix-Klasse.

+0

Ist ColorMatrix nicht mehr oder ändern sich die Farben auf Bildern? – Haukman