// ----------------------------------------------------------------------- // // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Animation { using System; using System.Diagnostics; using System.Linq; using System.Reactive.Linq; using Perspex.Threading; /// /// Utilities for creating animations. /// public static class Animate { /// /// The number of frames per second. /// public const int FramesPerSecond = 60; /// /// The time span of each frame. /// private static readonly TimeSpan Tick = TimeSpan.FromSeconds(1.0 / FramesPerSecond); /// /// Initializes static members of the class. /// static Animate() { Stopwatch = new Stopwatch(); Stopwatch.Start(); Timer = Observable.Interval(Tick, PerspexScheduler.Instance) .Select(_ => Stopwatch.Elapsed) .Publish() .RefCount(); } /// /// The stopwatch used to track time. /// /// /// The stopwatch used to track time. /// public static Stopwatch Stopwatch { get; private set; } /// /// Gets the animation timer. /// /// /// The animation timer ticks times per second. The /// parameter passed to a subsciber is the time span since the animation system was /// initialized. /// /// /// The animation timer. /// public static IObservable Timer { get; private set; } /// /// Gets a timer that fires every frame for the specified duration. /// /// The duration of the animation. /// /// An observable that notifies the subscriber of the progress along the animation. /// /// /// The parameter passed to the subscriber is the progress along the animation, with /// 0 being the start and 1 being the end. The observable is guaranteed to fire 0 /// immediately on subscribe and 1 at the end of the duration. /// public static IObservable GetTimer(TimeSpan duration) { var startTime = Stopwatch.Elapsed.Ticks; var endTime = startTime + duration.Ticks; return Timer .TakeWhile(x => x.Ticks < endTime) .Select(x => (x.Ticks - startTime) / (double)duration.Ticks) .StartWith(0.0) .Concat(Observable.Return(1.0)); } /// /// Animates a . /// /// The target object. /// The target property. /// The value of the property at the start of the animation. /// The value of the property at the end of the animation. /// The easing function to use. /// The duration of the animation. /// An that can be used to track or stop the animation. public static Animation Property( PerspexObject target, PerspexProperty property, object start, object finish, IEasing easing, TimeSpan duration) { var o = GetTimer(duration).Select(progress => easing.Ease(progress, start, finish)); return new Animation(o, target.Bind(property, o, BindingPriority.Animation)); } /// /// Animates a . /// /// The property type. /// The target object. /// The target property. /// The value of the property at the start of the animation. /// The value of the property at the end of the animation. /// The easing function to use. /// The duration of the animation. /// An that can be used to track or stop the animation. public static Animation Property( PerspexObject target, PerspexProperty property, T start, T finish, IEasing easing, TimeSpan duration) { var o = GetTimer(duration).Select(progress => easing.Ease(progress, start, finish)); return new Animation(o, target.Bind(property, o, BindingPriority.Animation)); } } }