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();