/// <summary>
/// 修改了一下,加了一个回调函数,并且代码加了些注释
/// </summary>
public class AnimatorEffect
{
//保存对控件操作的特性list
Dictionary<Object, List<AnimJob>> objects;
Timer tmrAnim = new Timer();
//回调函数
public delegate void FunctionDelegate(bool isSuccess, string msg = "");
private int fps = 25;
/// <summary>
/// fps越小越快,最小1,单位毫秒,默认25
/// </summary>
public int FPS
{
get
{
return fps;
}
set
{
fps = value;
tmrAnim.Interval = fps;
}
}
private class AnimJob
{
//特性
public string Property;
//值
public Object Value;
//是否执行完毕
public FunctionDelegate CallBack;
}
public AnimatorEffect()
{
objects = new Dictionary<object, List<AnimJob>>();
tmrAnim.Interval = 25;
tmrAnim.Enabled = true;
tmrAnim.Tick += tmrAnim_Tick;
}
public AnimatorEffect(int FPS)
{
objects = new Dictionary<object, List<AnimJob>>();
tmrAnim.Interval = 25;
tmrAnim.Enabled = true;
this.FPS = FPS;
tmrAnim.Tick += tmrAnim_Tick;
}
/// <summary>
///
/// </summary>
/// <param name="thisValue"></param>
/// <param name="desValue"></param>
/// <returns></returns>
private int getStep(int thisValue, int desValue)
{
//如果当前值和目标值相同,则不处理
if (thisValue == desValue) return 0;
//否则计算每次变化多少个像素
int step = (desValue - thisValue) / 3;
//等于0的情况为目标值和当前值在3以内
if (step == 0)
{
//如果目标值大于当前值,则为1,否则为-1
//在3个像素以内每次变化1
if (desValue > thisValue) step = 1;
else step = -1;
}
return step;
}
private double convertStepToPersent(int intStep)
{
double step = (double)intStep / 100;
if (Math.Abs(step) < 0.01)
{
if (intStep > 0) step = 0.01;
else step = -0.01;
}
return step;
}
void tmrAnim_Tick(object sender, EventArgs e)
{
//循环每一个控件,按照控件所对应的特性和值做相应处理
foreach (KeyValuePair<object, List<AnimJob>> item in objects)
{
if (item.Key is Control)
{
//获取控件
Control control = (Control)item.Key;
//获取该控件所有特性
List<AnimJob> jobs = item.Value;
//循环所有特性
foreach (AnimJob job in jobs)
{
//根据特性做相应处理
switch (job.Property.ToLower())
{
case "left":
int step = getStep(control.Left, (int)job.Value);
//step为0说明该特性设定已达目的,则删除该特性
if (step == 0)
{
jobs.Remove(job);
if (job.CallBack != null)
job.CallBack(true);
return;
}
//处理
control.Left += step;
break;
case "top":
step = getStep(control.Top, (int)job.Value);
if (step == 0)
{
jobs.Remove(job);
if (job.CallBack != null)
job.CallBack(true);
return;
}
control.Top += step;
break;
case "width":
step = getStep(control.Width, (int)job.Value);
if (step == 0)
{
jobs.Remove(job);
if (job.CallBack != null)
job.CallBack(true);
return;
}
control.Width += step;
break;
case "height":
step = getStep(control.Height, (int)job.Value);
if (step == 0)
{
jobs.Remove(job);
if (job.CallBack != null)
job.CallBack(true);
return;
}
control.Height += step;
break;
case "backcolor":
//颜色变化与上面思路一致,更改的是R/G/B三个值
Color val = (Color)job.Value;
int valR = val.R;
int valG = val.G;
int valB = val.B;
int stepR = getStep(control.BackColor.R, valR);
int stepG = getStep(control.BackColor.G, valG);
int stepB = getStep(control.BackColor.B, valB);
if (Math.Abs(stepR) + Math.Abs(stepG) + Math.Abs(stepB) == 0)
{
jobs.Remove(job);
if (job.CallBack != null)
job.CallBack(true);
return;
}
Color backColor = Color.FromArgb(control.BackColor.R + stepR,
control.BackColor.G + stepG, control.BackColor.B + stepB);
control.BackColor = backColor;
break;
case "opacity":
if (item.Key is Form)
{
Form form = (Form)control;
step = getStep((int)(form.Opacity * 100), (int)(Convert.ToDouble(job.Value) * 100));
if (step == 0)
{
jobs.Remove(job);
if (job.CallBack != null)
job.CallBack(true);
return;
}
form.Opacity += convertStepToPersent(step);
}
else
{
jobs.Remove(job);
if (job.CallBack != null)
job.CallBack(false, "只支持窗体调整透明度属性");
return;
}
break;
default:
jobs.Remove(job);
if (job.CallBack != null)
job.CallBack(false, "控件不支持[" + job.Property + "]属性");
return;
}
}
}
else
{
}
}
}
/// <summary>
/// 当多次设置一个控件的不同属性时,则加入list集合一同处理
/// </summary>
/// <param name="obj"></param>
/// <param name="prop"></param>
/// <param name="value"></param>
public void Set(Object obj, string prop, Object value, FunctionDelegate callBack = null)
{
if (!objects.ContainsKey(obj))
{
List<AnimJob> jobs = new List<AnimJob>();
objects.Add(obj, jobs);
}
AnimJob job = new AnimJob();
job.Property = prop;
job.Value = value;
job.CallBack = callBack;
if (!updateExistProperty(objects[obj], job)) objects[obj].Add(job);
}
/// <summary>
/// 判断对同一控件设定的属性是否已经存在,如果存在,则将目标值重新设定
/// </summary>
/// <param name="jobs"></param>
/// <param name="aJob"></param>
/// <returns></returns>
private bool updateExistProperty(List<AnimJob> jobs, AnimJob aJob)
{
bool have = false;
foreach (AnimJob job in jobs)
{
if (job.Property == aJob.Property)
{
have = true;
job.Value = aJob.Value;
break;
}
}
return have;
}
}