-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from stu98832/branch
Improve animation. Fix ArgumentOutOfRangeException issue, TabPage animation issue.
- Loading branch information
Showing
15 changed files
with
520 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
using MetroSet_UI.Enums; | ||
using System; | ||
using System.Windows.Forms; | ||
|
||
namespace MetroSet_UI.Animates | ||
{ | ||
// interpolation animate | ||
public abstract class Animate<T> : IDisposable | ||
{ | ||
/// <summary> | ||
/// Call when animation update | ||
/// </summary> | ||
public Action<T> Update { get; set; } | ||
|
||
/// <summary> | ||
/// Call when animation complate | ||
/// </summary> | ||
public MethodInvoker Complete { get; set; } | ||
|
||
#region Internal Vars | ||
// a bad way to record time... | ||
private DateTime _lastUpdateTime; | ||
// I use timer instead of thread, so you can modify control without Control.Invoke | ||
private Timer _animateTimer; | ||
// reverse animate | ||
private bool _reverse; | ||
#endregion | ||
|
||
#region Constructors | ||
// choose best interval for yourself | ||
public Animate(int updateInterval = 16) | ||
{ | ||
_animateTimer = new Timer() | ||
{ | ||
Interval = updateInterval, | ||
Enabled = false, | ||
}; | ||
_animateTimer.Tick += this.OnFrameUpdate; | ||
_reverse = false; | ||
Alpha = 0.0; | ||
} | ||
#endregion | ||
|
||
#region Functions | ||
// just set once, and use start, back or reverse to play animate | ||
public void Setting(int duration, T initial, T end, EasingType easing = EasingType.Linear) | ||
{ | ||
InitialValue = initial; | ||
EndValue = end; | ||
EasingType = easing; | ||
Duration = duration; | ||
} | ||
|
||
// start animate with default setting | ||
public void Start() | ||
{ | ||
_reverse = false; | ||
Alpha = 0.0; | ||
Play(); | ||
} | ||
|
||
// back animate with default setting | ||
public void Back() | ||
{ | ||
_reverse = true; | ||
Alpha = 1.0; | ||
Play(); | ||
} | ||
|
||
// start animate with default setting | ||
public void Start(int duration) | ||
{ | ||
_reverse = false; | ||
Alpha = 0.0; | ||
Duration = duration; | ||
Play(); | ||
} | ||
|
||
// back animate with default setting | ||
public void Back(int duration) | ||
{ | ||
_reverse = true; | ||
Alpha = 1.0; | ||
Duration = duration; | ||
Play(); | ||
} | ||
|
||
// reverse animate | ||
public void Reverse() | ||
{ | ||
Reverse(!_reverse); | ||
} | ||
|
||
// reverse animate | ||
public void Reverse(bool val) | ||
{ | ||
_reverse = val; | ||
|
||
if (!Active) | ||
Play(); | ||
} | ||
|
||
// play animate | ||
public void Play() | ||
{ | ||
_lastUpdateTime = DateTime.Now; | ||
Active = true; | ||
_animateTimer.Enabled = true; | ||
_animateTimer.Start(); | ||
} | ||
|
||
public void Pause() | ||
{ | ||
_animateTimer.Stop(); | ||
_animateTimer.Enabled = false; | ||
Active = false; | ||
} | ||
|
||
public void Stop() | ||
{ | ||
Pause(); | ||
Alpha = _reverse ? 1.0 : 0.0; | ||
} | ||
|
||
// start animate with specific setting | ||
public void Start(int duration, T initial, T end, EasingType easing = EasingType.Linear) | ||
{ | ||
Setting(duration, initial, end, easing); | ||
Start(); | ||
} | ||
|
||
// back animate with specific setting | ||
public void Back(int duration, T initial, T end, EasingType easing = EasingType.Linear) | ||
{ | ||
Setting(duration, initial, end, easing); | ||
Back(); | ||
} | ||
#endregion | ||
|
||
#region Events | ||
// process frame | ||
private void OnFrameUpdate(object sender, EventArgs e) | ||
{ | ||
DateTime updateTime = DateTime.Now; | ||
double elapsed; | ||
|
||
if (Duration == 0) | ||
elapsed = 1.0; | ||
else | ||
elapsed = (updateTime - _lastUpdateTime).TotalMilliseconds / Duration; | ||
|
||
_lastUpdateTime = updateTime; | ||
Alpha = Math.Max(0.0, Math.Min(Alpha + (_reverse ? -elapsed : elapsed), 1.0)); | ||
|
||
Update?.Invoke(Value); | ||
|
||
if (Alpha == 0.0 || Alpha == 1.0) | ||
{ | ||
Pause(); | ||
Complete?.Invoke(); | ||
} | ||
} | ||
#endregion | ||
|
||
#region Properties | ||
// progress. value between 0 and 1 | ||
public double Alpha { get; set; } | ||
|
||
// animate duration | ||
// recorded for calculating elapsed alpha | ||
// if you use reverse animate when animate avtiving | ||
// the real duration will different with the duration you set | ||
public int Duration { get; set; } | ||
|
||
// initial state of value | ||
public T InitialValue { get; private set; } | ||
|
||
public abstract T Value { get; } | ||
|
||
// final state of value | ||
public T EndValue { get; private set; } | ||
|
||
// easing type | ||
public EasingType EasingType { get; private set; } | ||
|
||
// active if the animate is running | ||
public bool Active { get; private set; } | ||
|
||
// store you own variable here | ||
public object Tag { get; set; } | ||
#endregion | ||
|
||
#region Dispose | ||
public void Dispose() | ||
{ | ||
_animateTimer.Dispose(); | ||
} | ||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System.Drawing; | ||
|
||
namespace MetroSet_UI.Animates | ||
{ | ||
public class ColorAnimate : Animate<Color> | ||
{ | ||
public override Color Value => | ||
Color.FromArgb( | ||
(byte)Interpolation.ValueAt(InitialValue.A, EndValue.A, Alpha, EasingType), | ||
(byte)Interpolation.ValueAt(InitialValue.R, EndValue.R, Alpha, EasingType), | ||
(byte)Interpolation.ValueAt(InitialValue.G, EndValue.G, Alpha, EasingType), | ||
(byte)Interpolation.ValueAt(InitialValue.B, EndValue.B, Alpha, EasingType) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace MetroSet_UI.Animates | ||
{ | ||
public class DoubleAnimate : Animate<double> | ||
{ | ||
public override double Value => | ||
Interpolation.ValueAt(InitialValue, EndValue, Alpha, EasingType); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace MetroSet_UI.Animates | ||
{ | ||
public class IntAnimate : Animate<int> | ||
{ | ||
public override int Value => | ||
(int)Interpolation.ValueAt(InitialValue, EndValue, Alpha, EasingType); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
using System; | ||
using MetroSet_UI.Enums; | ||
|
||
namespace MetroSet_UI.Animates | ||
{ | ||
// for animate | ||
public class Interpolation | ||
{ | ||
public static double ValueAt(double initial, double end, double alpha, EasingType easing) | ||
{ | ||
switch (easing) | ||
{ | ||
default: | ||
case EasingType.None: | ||
case EasingType.Linear: | ||
return (end * alpha) + (initial * (1 - alpha)); | ||
case EasingType.QuadIn: | ||
{ | ||
double factor = alpha * alpha; | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.QuadOut: | ||
{ | ||
double factor = (2 - alpha) * alpha; | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.QuadInOut: | ||
{ | ||
double mid = initial + (end - initial) / 2.0; | ||
if (alpha <= 0.5) | ||
return ValueAt(initial, mid, alpha * 2, EasingType.QuadIn); | ||
else | ||
return ValueAt(mid, end, (alpha - 0.5) * 2, EasingType.QuadOut); | ||
} | ||
case EasingType.CubeIn: | ||
{ | ||
double factor = alpha * alpha * alpha; | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.CubeOut: | ||
{ | ||
double factor = -(alpha - 1); | ||
factor = -(factor * factor * factor) + 1; | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.CubeInOut: | ||
{ | ||
double mid = initial + (end - initial) / 2.0; | ||
if (alpha <= 0.5) | ||
return ValueAt(initial, mid, alpha * 2, EasingType.CubeIn); | ||
else | ||
return ValueAt(mid, end, (alpha - 0.5) * 2, EasingType.CubeOut); | ||
} | ||
case EasingType.QuartIn: | ||
{ | ||
double factor = alpha * alpha * alpha * alpha; | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.QuartOut: | ||
{ | ||
double factor = -(alpha - 1); | ||
factor = 1-(factor * factor * factor * factor); | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.QuartInOut: | ||
{ | ||
double mid = initial + (end - initial) / 2.0; | ||
if (alpha <= 0.5) | ||
return ValueAt(initial, mid, alpha * 2, EasingType.QuartIn); | ||
else | ||
return ValueAt(mid, end, (alpha - 0.5) * 2, EasingType.QuartOut); | ||
} | ||
case EasingType.QuintIn: | ||
{ | ||
double factor = alpha * alpha * alpha * alpha * alpha; | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.QuintOut: | ||
{ | ||
double factor = -(alpha - 1); | ||
factor = 1-(factor * factor * factor * factor * factor); | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.QuintInOut: | ||
{ | ||
double mid = initial + (end - initial) / 2.0; | ||
if (alpha <= 0.5) | ||
return ValueAt(initial, mid, alpha / 0.5, EasingType.QuintIn); | ||
else | ||
return ValueAt(mid, end, (alpha - 0.5) / 0.5, EasingType.QuintOut); | ||
} | ||
case EasingType.SineIn: | ||
{ | ||
double factor = 1 - Math.Cos(Math.PI / 2 * alpha); | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.SineOut: | ||
{ | ||
double factor = Math.Sin(Math.PI / 2 * alpha); | ||
return (end * factor) + (initial * (1 - factor)); | ||
} | ||
case EasingType.SineInOut: | ||
{ | ||
if (alpha <= 0.5) | ||
return ValueAt(initial, (initial + end) / 2.0, alpha * 2, EasingType.SineIn); | ||
else | ||
return ValueAt((initial + end) / 2.0, end, (alpha-0.5) * 2, EasingType.SineOut); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System.Drawing; | ||
|
||
namespace MetroSet_UI.Animates | ||
{ | ||
public class PointFAnimate : Animate<PointF> | ||
{ | ||
public override PointF Value => | ||
new PointF( | ||
(float)Interpolation.ValueAt(InitialValue.X, EndValue.X, Alpha, EasingType), | ||
(float)Interpolation.ValueAt(InitialValue.Y, EndValue.Y, Alpha, EasingType) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System.Drawing; | ||
|
||
namespace MetroSet_UI.Animates | ||
{ | ||
public class SizeFAnimate : Animate<SizeF> | ||
{ | ||
public override SizeF Value => | ||
new SizeF( | ||
(float)Interpolation.ValueAt(InitialValue.Width, EndValue.Width, Alpha, EasingType), | ||
(float)Interpolation.ValueAt(InitialValue.Height, EndValue.Height, Alpha, EasingType) | ||
); | ||
} | ||
} |
Oops, something went wrong.