定义独立动画接口
public interface IAnimator
{
IAnimator Start();
IAnimator Stop();
IAnimator Reset();
IAnimator SetDuration(int times);
IAnimator SetNext(IAnimator next);
}
实现接口,创建值动画类
using Doraemon.Common.Utility;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Doraemon.Common.Animation
{
public class ValueAnimator<T> : IAnimator
{
private T start = default(T);
private T end = default(T);
private int times = 1000;
private T curValue;
private long ticks = 0;
private IAnimator next = null;
private Timer timer;
public T CurValue
{
get => curValue;
set
{
if ((IComparable)curValue != (IComparable)value)
{
curValue = value;
Update?.Invoke(this, curValue);
}
}
}
public ValueAnimator(T start, T end)
{
CreateBase(start, end);
}
private void CreateBase(T start, T end)
{
this.start = start;
this.end = end;
timer = new Timer();
timer.Enabled = false;
timer.Interval = 10;
timer.Tick += Timer_Tick;
}
public IAnimator Start()
{
timer.Start();
return this;
}
public IAnimator Stop()
{
timer.Stop();
return this;
}
public IAnimator Reset()
{
timer.Stop();
CurValue = default(T);
return this;
}
public event Handler<ValueAnimator<T>, T> Update;
public event Handler<ValueAnimator<T>, T> Done;
private List<string> strs = new List<string>();
private void Timer_Tick(object sender, EventArgs e)
{
if (ticks == 0)
ticks = SystemHelper.Ticks;
double curRate = (SystemHelper.Ticks - ticks) / (times * 1000.0);
double v1 = double.Parse(start.ToString());
double v2 = double.Parse(end.ToString());
bool reverse = (v2 - v1) < 0;
double val = (v1 + (v2 - v1) * curRate);
if ((!reverse && val >= v2)
|| (reverse && val <= v2))
{
CurValue = end;
Stop();
ticks = 0;
Done?.Invoke(this, CurValue);
if (next != null)
next.Start();
}
else
CurValue = (T)Convert.ChangeType(val, typeof(T));
}
public IAnimator SetNext(IAnimator ani)
{
next = ani;
return this;
}
public IAnimator SetDuration(int times)
{
this.times = times;
return this;
}
}
}
实现对象属性动画
using System;
using System.Reflection;
namespace Doraemon.Common.Animation
{
public class ObjectAnimator : IAnimator
{
private object obj = null;
private string propertyName = string.Empty;
private IAnimator animator;
private ObjectAnimator(object obj, string propertyName, int start, int end)
{
this.obj = obj;
this.propertyName = propertyName;
var ani = new ValueAnimator<int>(start, end);
this.animator = ani;
ani.Update += Ani_Update;
}
private ObjectAnimator(object obj, string propertyName, double start, double end)
{
this.obj = obj;
this.propertyName = propertyName;
var ani = new ValueAnimator<double>(start, end);
this.animator = ani;
ani.Update += Ani_Update1;
}
private void Ani_Update1(ValueAnimator<double> sender, double e)
{
SetValue<double>(e);
}
private void SetValue<T>(T e)
{
try
{
Type t = this.obj.GetType();
PropertyInfo pi = t.GetProperty(propertyName);
pi.SetValue(this.obj, e);
}
catch
{
animator.Stop();
}
}
private void Ani_Update(ValueAnimator<int> sender, int e)
{
SetValue<int>(e);
}
public static ObjectAnimator OfInt(object obj, string propertyName, int start, int end)
{
return new ObjectAnimator(obj, propertyName, start, end);
}
public static ObjectAnimator OfDouble(object obj, string propertyName, double start, double end)
{
return new ObjectAnimator(obj, propertyName, start, end);
}
public IAnimator Start()
{
return animator.Start();
}
public IAnimator Stop()
{
return animator.Stop();
}
public IAnimator Reset()
{
return animator.Reset();
}
public IAnimator SetDuration(int times)
{
return animator.SetDuration(times);
}
public IAnimator SetNext(IAnimator next)
{
return animator.SetNext(next);
}
}
}
应用
在WinForm中调用
IAnimator ani1 = ObjectAnimator.OfDouble(this, "Opacity", 1, 0).SetDuration(200);
IAnimator ani2 = ObjectAnimator.OfDouble(this, "Opacity", 0, 1).SetDuration(200);
ani1.SetNext(ani2);
ani2.SetNext(ani1);
ani1.Start();
|