Click here to Skip to main content
Click here to Skip to main content

Tagged as

Circular Progress Indicator

, 1 Jul 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
Firefox like circular progress indicator

Introduction

I've always liked the little circular progress indicator on Firefox top right corner when loading a page but I couldn't find any like it to use with my projects, so I've made one myself.

Using the Code

Using the control is very simple, there are only four properties and two methods that you need to be aware of:

  • CircleColor - Changes the base color of the circles
  • CircleSize - Changes the diameter of the circles, this value is relative and proportional to the control size and ranges between 0.1 and 1.0
  • AutoStart - Sets if the animation should start automatically
  • AnimationSpeed - Sets the animation speed 
  • NumberOfCircles - Sets the maximum number of circles that can be drawn in the control, this value must be greater than 0
  • NumberOfVisibleCircles - Sets the number of circles that are visible in the control, must always be less or equal than the NumberOfCircles
  • Percentage - Sets a percentage value that can be shown in the center of the control, this value must be between 0 and 100
  • ShowPercentage - Sets a value that allows to show or hide the percentage value
  • ShowText - Sets a value that allows to show the control text
  • TextDisplay - This property is just a helper property, it allows to enable or disable both text and percentage with one property
  • Rotation - Sets the direction in which the control will rotate

To start the animation, just call Start():

progressIndicator.Start(); 

And to stop it, just call Stop():

progresIndicator.Stop();

The Control Code

Drawing the Circles

The circles are drawn around a circumference with the diameter of the control. Since the number of circles is variable, we need to calculate the rotation angle for each circle. The minimum number of circles must be 1 with no upper limit control. Drawing the circles is done using a call to RotateTransform that rotates the drawing position to the angle passed as a parameter. Drawing the circles in sequence, decreasing the amount of alpha in the circle color gives the fading effect of the control. To animate, the control is redrawn at time intervals always changing the position of the darker circle by one place forward, giving the illusion of motion. The control can be rotated clockwise or counter-clockwise and direction of rotation is achieved by multiplying the angle by 1 or -1. Checking the code, this line is found:

e.Graphics.RotateTransform(angle * _value * (int)_rotation);

This piece of code sets the start position of each rotation phase multiplying the section angle by a value that is incremented by an internal timer. The maximum number of circles shown at a given time is defined by the NumberOfVisibleCircles property. This property determines the effective number of circles that are drawn in the control, this is different from the NumberOfCircles property. This last property sets the number of circles that can be drawn, is like reserving spaces for the circles even if we don't use them all. This gives the effect of tightening the circles together when the number of visible circles decreases and the opposite effect when it increases.

float angle = 360.0F / _numberOfCircles;

GraphicsState oldState = e.Graphics.Save();

e.Graphics.TranslateTransform(Width / 2.0F, Height / 2.0F);
e.Graphics.RotateTransform(angle * _value * (int)_rotation);
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

for (int i = 1; i <= _numberOfCircles; i++)
{
    int alphaValue = (255.0F * (i / (float)_numberOfVisibleCircles)) > 255.0 ? 0 : 
	(int)(255.0F * (i / (float)_numberOfVisibleCircles));
    int alpha = _stopped ? (int)(255.0F * (1.0F / 8.0F)) : alphaValue;

    Color drawColor = Color.FromArgb(alpha, _circleColor);

    using (SolidBrush brush = new SolidBrush(drawColor))
    {
        float sizeRate = 4.5F / _circleSize;
        float size = Width / sizeRate;

        float diff = (Width / 4.5F) - size;

        float x = (Width / 9.0F) + diff;
        float y = (Height / 9.0F) + diff;
        e.Graphics.FillEllipse(brush, x, y, size, size);
        e.Graphics.RotateTransform(angle * (int)_rotation);
    }
}

e.Graphics.Restore(oldState);

Drawing the Percentage and the Text

The percentage is an optional feature, since the primary purpose isn't to show a progress value but that something is going on. The percentage text isn't shown by default and wasn't even part of the original idea. Anyway I have been reading some comments from people requesting new features and giving some nice ideas that I've decided to update the control and implement some new features. One of them was this one. The percentage is set through the Percentage property and can be enabled and disabled from the ShowPercentage property. The Text property follows the same reasoning. It wasn't part of the original plan, but as SohjSolwin suggested, it can be useful in some cases, we never know when or where this control will be used. So, from this version on, the control has the ability of drawing both of them like shown below:

string percent = GetDrawText();

if (!string.IsNullOrEmpty(percent))
{
    SizeF textSize = e.Graphics.MeasureString(percent, Font);
    float textX = (Width / 2.0F) - (textSize.Width / 2.0F);
    float textY = (Height / 2.0F) - (textSize.Height / 2.0F);
    StringFormat format = new StringFormat
    {
        Alignment = StringAlignment.Center,
        LineAlignment = StringAlignment.Center
    };

    RectangleF rectangle = new RectangleF(textX, textY, textSize.Width, textSize.Height);
        

    using (SolidBrush textBrush = new SolidBrush(ForeColor))
    {
        e.Graphics.DrawString(percent, Font, textBrush, rectangle, format);
    } 
}

Why both Percentage and the Text?

When the control is being used to show progress, it is possible to show a message about what is going on and at the same time the progress percentage. Both of them are independent and have different purposes. Even if they are drawn at the same time internally, if I just need to change the value of the percentage, it's easier to do this:

progressIndicator.Percentage = 50.25F;

And let the control add the "%" sign and do the rest of the formatting. It's much more intuitive and simple than this:

progressIndicator.Text = string.Format("{0:0:##} %}, 50.25F);

On the other hand, the percentage property doesn't allow text, so it's needs another field to set the text to draw. The final string that is displayed is built using the Text and the Percentage property in the method displayed below, the method checks the values of the _showText and _showPercentage fields and constructs a string based on their values, returning an empty string if both fields are set to false.

private string GetDrawText()
{
    string percent = string.Format(CultureInfo.CurrentCulture, "{0:0.##} %", _percentage);

    if (_showText && _showPercentage)
        return string.Format("{0}{1}{2}", percent, Environment.NewLine, Text);

    if (_showText)
        return Text;

    if (_showPercentage)
        return percent;

    return string.Empty;
}

The rest of the control code is short and simple to understand, so I've decided to remove it from the article leaving only the pieces that matter. If you have any questions, please leave a comment.

Points of Interest

There's nothing more to it. It is particularly useful in situations where the progress bar hasn't made any progress for a long time and we want to pass the message that something is being done. Mainly, it has been fun to program. Smile | :)

Credits

I would like to thank SohjSolwin for his contribution with the rotation and number of visible circles part of the code that I've included in this release with minor modifications, and also for the text drawing suggestion instead of only showing the percentage.

History

  • 2nd November, 2008: Initial post
  • 26th June, 2010: Update to version 1.1, new features are:
    • Variable number of circles (version 1 has a fixed number of 8)
    • It is possible to draw a percentage value
  • 1st July, 2010: Update to version 1.2, new features are:
    • Rotation can be clockwise or counter-clockwise
    • It is possible to draw a text string in addition to the percentage value
    • Variable number of visible circles (version 1.1 has a fixed number of 8)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Nitoc3
Software Developer
Portugal Portugal
No Biography provided

Comments and Discussions

 
QuestionFreeze image (imagem estática) PinmemberMember 1005105726-Feb-14 12:03 
AnswerRe: Freeze image (imagem estática) PinmemberNitoc327-Feb-14 8:59 
GeneralMy vote of 4 PinmemberPrasyee5-Mar-13 18:33 
GeneralMy vote of 5 PinmemberIFFI11-Dec-12 5:55 
QuestionThank you! PinmemberIgnacioooooo21-Nov-12 8:39 
QuestionProblem while launching external app Pinmemberalex__b6-Aug-12 20:15 
QuestionExcellent. PinmemberPHS24123-Apr-12 23:57 
GeneralMy vote of 5 PinmemberVano Maisuradze26-Mar-12 1:49 
QuestionPermission [modified] PinmemberxivSolutions19-Feb-12 14:00 
AnswerRe: Permission PinmemberNitoc320-Feb-12 7:39 
GeneralNice! PinmemberxivSolutions31-Jan-12 17:40 
QuestionIts awesome. Thanks. Pinmemberpkkalra197826-Sep-11 22:16 
GeneralLike !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Pinmemberraananv31-Aug-11 13:48 
GeneralMy vote of 5 PinmemberTheF®eeSurfer6-Apr-11 1:34 
GeneralAnother new vote Pinmemberapiegoku22-Sep-10 12:08 
GeneralMy vote of 5 PinmemberVUnreal21-Sep-10 12:00 
GeneralVery usefull progress indicator Pinmemberredhatee200611-Aug-10 6:44 
GeneralRe: Very usefull progress indicator PinmemberNitoc317-Aug-10 8:11 
GeneralMy vote of 5 Pinmemberkobymeir17-Jul-10 5:40 
GeneralMy vote of 5 PinmemberHuseyin OZCAKIR10-Jul-10 0:14 
GeneralMy vote of 5 Pinmembergarycoggins8-Jul-10 5:12 
Generaluse of control PinmemberMember 347198330-Jun-10 9:48 
GeneralRe: use of control PinmemberSohjSolwin1-Jul-10 12:12 
GeneralA few updates and request for permission PinmemberSohjSolwin29-Jun-10 12:17 
GeneralRe: A few updates and request for permission PinmemberNitoc330-Jun-10 2:13 
GeneralRe: A few updates and request for permission PinmemberSohjSolwin30-Jun-10 8:52 
GeneralRe: A few updates and request for permission PinmemberNitoc330-Jun-10 9:28 
GeneralRe: A few updates and request for permission PinmemberSohjSolwin2-Jul-10 4:27 
GeneralRe: A few updates and request for permission [modified] PinmemberNitoc32-Jul-10 5:10 
Generalfun PinmemberMember 14901625-Jun-10 21:32 
GeneralRe: fun PinmemberNitoc326-Jun-10 8:39 
QuestionCan it be used on C# win mobile? Pinmemberaaronlzw_2114-Oct-09 16:39 
AnswerRe: Can it be used on C# win mobile? PinmemberNitoc315-Oct-09 4:48 
QuestionRe: Can it be used on C# win mobile? Pinmemberstijn.vandenbroucke9-Oct-11 3:25 
QuestionPercentage PinmemberOKA13325-Aug-09 14:58 
AnswerRe: Percentage PinmemberNitoc326-Aug-09 4:58 
GeneralRe: Percentage PinmemberOKA13326-Aug-09 14:54 
GeneralFading Colors Pinmemberkjward20-Jul-09 7:21 
GeneralRe: Fading Colors PinmemberNitoc326-Aug-09 4:53 
QuestionHow to use this control?? PinmemberPayam Rastogi11-Feb-09 3:58 
AnswerRe: How to use this control?? PinmemberNitoc311-Feb-09 4:44 
GeneralRe: How to use this control?? PinmemberPayam Rastogi11-Feb-09 4:54 
GeneralRe: How to use this control?? PinmemberNitoc311-Feb-09 5:23 
GeneralUsefull control PinmemberLuc Bardez18-Dec-08 5:44 
GeneralRe: Usefull control PinmemberNitoc318-Dec-08 14:56 
QuestionThis control in WPF? PinmemberYogesh Jagota9-Nov-08 7:36 
AnswerRe: This control in WPF? PinmemberYogesh Jagota9-Nov-08 8:00 
GeneralBy the way PinmemberD Strauss3-Nov-08 20:57 
GeneralAwesome!!! PinmemberD Strauss3-Nov-08 20:54 
GeneralRe: Awesome!!! PinmemberNitoc34-Nov-08 3:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141220.1 | Last Updated 1 Jul 2010
Article Copyright 2008 by Nitoc3
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid