Theun Arbeider
Theun Arbeider

Reputation: 5419

Creating a fade out label

This might seem like a simple question...

I'm looking for the Label.Opacity property in C# Winforms.

What I wish to do is have a method that fade's out a label gradually. By means of a timer perhaps?

Since there is not Opacity I'm trying to set it's transperency to higher numbers untill it's high enough that the item should be invisible. But I can't seem to make this work.

Currently I have:

public FadeLabel()
{
    MyTimer timer = new MyTimer();
    this.TextChanged += (s, ea) =>
    {
        if (timer.IsActive)
        {
            timer.Reset();
        }
        else
        {
            timer.WaitTime.Miliseconds = 500;
            timer.Start();
            timer.Completed += (a) =>
            {
                int i = 0;
                Timer tm = new Timer();
                tm.Interval = 1;
                tm.Tick += (sa, aea) =>
                {
                    i++;
                    this.ForeColor = Color.FromArgb(i, Color.Black);
                    this.BackColor = Color.FromArgb(i, Color.White);
                    this.Invalidate();
                    if (i == 255)
                    {
                        tm.Stop();
                    }
                };
                tm.Start();
            };
        }
    };
}

Upvotes: 8

Views: 19755

Answers (5)

Delphis
Delphis

Reputation: 11

Here's what I wrote. It also handles labels of different colors (e.g. green, red)

Instance the class, attach to the label any time. After you set the message and the initial foreground color, then call setColorSteps and how many steps you want.

When you want to run the fade, call doFade()

Props to OP for the timer loop event, which I used when I wrote this solution that worked for what I needed.

/// <summary>
/// Fade a label - Derek Piper 2019
/// </summary>
public class LabelFader
{
    Label label;
    List<ColorStep> colorSteps = new List<ColorStep>();

    public void attachToControl(Label useLabel)
    {
        this.label = useLabel;
    }

    public void setColorSteps(int numSteps)
    {
        if (this.label != null)
        {
            ColorStep start = new ColorStep(this.label.ForeColor);
            ColorStep end = new ColorStep(this.label.BackColor);
            int redIncrement = ((end.R - start.R) / numSteps);
            int greenIncrement = ((end.G - start.G) / numSteps);
            int blueIncrement = ((end.B - start.B) / numSteps);
            this.colorSteps = new List<ColorStep>();
            for (int i = 0; i <= numSteps; i++)
            {
                ColorStep newStep = new ColorStep();
                if (redIncrement > 0)
                {
                    newStep.R = start.R + (i * redIncrement);
                }
                else
                {
                    newStep.R = start.R - (i * redIncrement);
                }
                if (greenIncrement > 0)
                {
                    newStep.G = start.G + (i * greenIncrement);
                }
                else
                {
                    newStep.G = start.G - (i * greenIncrement);
                }
                if (blueIncrement > 0)
                {
                    newStep.B = start.B + (i * blueIncrement);
                }
                else
                {
                    newStep.B = start.B - (i * blueIncrement);
                }
                this.colorSteps.Add(newStep);
            }
        }
    }

    public void doFade(int speedMs = 40)
    {
        Timer tm = new Timer();
        tm.Interval = speedMs;
        int step = 0;
        int end = this.colorSteps.Count;
        if (this.colorSteps.Count > 0)
        {
            tm.Tick += (sa, aea) =>
            {
                ColorStep thisStep = this.colorSteps[step];
                this.label.ForeColor = Color.FromArgb(thisStep.R, thisStep.G, thisStep.B);
                step++;
                if (step >= end)
                {
                    tm.Stop();
                    this.label.Visible = false;
                }
            };
            tm.Start();
        }
    }
}

class ColorStep
{
    public int R = 0;
    public int G = 0;
    public int B = 0;

    public ColorStep()
    {
    }

    public ColorStep(Color from)
    {
        this.setFromColor(from);
    }

    public void setFromColor(Color from)
    {
        this.R = from.R;
        this.G = from.G;
        this.B = from.B;
    }

    public Color getColor()
    {
        return Color.FromArgb(this.R, this.G, this.B);
    }
}

Upvotes: 1

user3305711
user3305711

Reputation: 451

This is a more complete and elegant solution:

// Aufruf der Methode aus dem Worker-Thread
private void OnFadeTimerEvent(object sender, ElapsedEventArgs e)
{
    this.Invoke(new Action(() => FadeOutLabel()));
}

private void FadeOutLabel()
{
    if (labelStartHelp.ForeColor.GetBrightness() <= 0.01)
    {
        FadeTimer.Enabled = false;
        labelStartHelp.Visible = false;
        return;
    }
    HslColor hsl = new HslColor(labelStartHelp.ForeColor);
    hsl.L -= 0.002; // Brightness is here lightness
    labelStartHelp.ForeColor = (System.Drawing.Color)hsl.ToRgbColor();
}

using APCyotek HslColor class: http://cyotek.com/downloads/view/Cyotek.Windows.Forms.ColorPicker.zip/Cyotek.Windows.Forms.ColorPicker/Cyotek.Windows.Forms.ColorPicker/HslColor.cs

dont know about license though. Hope u like it!

Upvotes: 1

BJS3D
BJS3D

Reputation: 169

One way that I've found to create a smooth fade is to adjust the ForeColor RGB variables using a timer. This gives you control over the duration and allows you to finesse the transition from current ForeColor values to the target values.

private void timer1_Tick(object sender, EventArgs e)
    {
        // timer interval set to 10 to ensure smooth fading
        // declared int: r = 0, g = 215 and b = 180
        // target values are r = 32, g = 32 and b = 32 to match BackColor
        fade++;
        if (fade >= 500) // arbitrary duration set prior to initiating fade
        {
            if (r < 32) r++; // increase r value with each tick
            if (g > 32) g--; // decrease g value with each tick
            if (b > 32) b--; // decrease b value with each tick
            label1.ForeColor = Color.FromArgb(255, r, g, b);
            if (r == 32 && g == 32 && b == 32) // arrived at target values
            {
                // fade is complete - reset variables for next fade operation
                label1.ForeColor = Color.FromArgb(255, 0, 215, 180);
                label1.Text = "";
                fade = 0;
                r = 0;
                g = 215;
                b = 180;
                timer1.Enabled = false;
            }
        }
    }

Upvotes: 4

Zerato
Zerato

Reputation: 703

This is what I'm using to fade out labels:

    label1.Text = "I'm fading out now";
    label1.ForeColor = Color.Black;
    timer1.Start();

    private void timer1_Tick(object sender, EventArgs e)
    {
        int fadingSpeed = 3;
        label1.ForeColor = Color.FromArgb(label1.ForeColor.R + fadingSpeed, label1.ForeColor.G + fadingSpeed, label1.ForeColor.B + fadingSpeed);

        if (label1.ForeColor.R >= this.BackColor.R)
        {
            timer1.Stop();
            label1.ForeColor = this.BackColor;
        }
    }

Maybe not the best solution but I'm still a beginner so this is what I can contribute with. I put timer1.Interval at minimum and played with fadingSpeed until it looked good.

Upvotes: 14

Anton Gogolev
Anton Gogolev

Reputation: 115751

Does your timer block the UI thread? If so, you won't see anything until after it elapses. A quick way to fix things will be to call Application.DoEvents instead of this.Invalidate();.

Upvotes: 3

Related Questions