2009-04-02 34 views
7

Tôi muốn tạo một hộp văn bản trong .NET "glow" màu vàng, và sau đó "phai" thành màu trắng (về cơ bản, bằng cách tăng dần độ sáng). Tôi nghĩ rằng Stackoverflow thực hiện điều này sau khi bạn đã đăng câu trả lời. Tôi biết rằng tăng độ sáng không phải là tất cả những gì đơn giản (nó không chỉ tăng/giảm RGB đồng đều), nhưng tôi không chắc chắn làm thế nào để làm điều này.Làm mờ một màu trắng (tăng độ sáng)

Độ chính xác màu hoàn hảo không quan trọng đối với điều này. Tôi đang sử dụng C#, mặc dù VB ví dụ sẽ là tốt, quá.

Chỉnh sửa: Điều này dành cho Winforms.

Trả lời

8

Đây có thể là nhiều hơn bạn cần, đây là mã cho lớp tôi sử dụng:

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; 
    } 
} 

này sử dụng DataEventArgs<T> (hình dưới đây)

/// <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; 
    } 
} 

sử dụng trong hình thức của bạn như thế này:

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

Điều này rất thông minh, cảm ơn :) Tôi đã sửa đổi nó (để vượt qua một tham số Ẩn để khi hoạt ảnh kết thúc, kiểm soát được ẩn) và thêm nó vào baseclass của tôi, bây giờ tất cả các hình thức kế thừa của tôi có khả năng ghi đè setColor và sử dụng nó . Tôi đã không tìm thấy một cách thanh lịch để có thể vượt qua một điều khiển nơi các hình ảnh động sẽ xảy ra, thay vì "hardcoding" nó trong setColor. Bất kỳ ý tưởng? –

+0

Đã không thử nó, nhưng có lẽ một phương pháp mở rộng trên điều khiển ... sau đó bạn có thể gọi nó như thế này "invokeOnFormThread (myControl.SetColor (e));" –

+0

Cảm ơn, sẽ điều tra.Trong thời gian đó, tôi đã sửa đổi runColorLoop() để tôi có thể chuyển màu, thời lượng, điều khiển và nếu tôi muốn ẩn sau khi hoạt ảnh kết thúc, theo cách đó tôi có thể sử dụng tất cả điều này trong lớp cơ sở và mọi thứ được thừa hưởng biểu mẫu có thể sử dụng base.runColorLoop (x, y, z, f); –

0

Ban đầu bạn không chỉ định công nghệ khi tôi gửi câu trả lời này, nhưng dưới đây là cách bạn làm điều đó bằng cách sử dụng jQuery.

UI/Effects/Highlight.

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

anh ấy nói "winforms" –

+0

Bah, dường như tương lai là "ứng dụng web" trong "đám mây" trên "người bạn đồng hành điện tử" của bạn. Vì vậy, anh ta nên bọc Webkit trong ứng dụng của mình và sử dụng Hiệu ứng CSS và Ảnh động mà nó hỗ trợ! – JeeBee

+0

Tôi cảm thấy rất retro :) –

2

Chỉ nội suy giữa các màu dựa trên thời gian.

Nếu màu cam của bạn là (r1, g1, b1) và bạn muốn mờ sang màu khác (r2, g2, b2), công thức nội suy tuyến tính là (r1 + (r2-r1) * t, g1 + (g2-g1) * t, b1 + (b2-b1) * t), trong đó t nằm trong khoảng [0.0 1.0].

Trong ví dụ của bạn, màu đầu tiên của bạn có thể giống như (255,200,0) và màu thứ hai của bạn sẽ là (255,255,255).

Nếu bạn muốn chuyển tiếp mượt mà hơn, hãy tìm các cách nội suy khác nhau.

0

Nếu bạn muốn làm điều đó một cách thuận tiện và trơn tru, hãy xem lớp ColorMatrix.

+0

Không phải là ColorMatrix nhiều hay thay đổi màu sắc trên hình ảnh? – Haukman

Các vấn đề liên quan