Browse Source

Split the global timer for Transitions and Animations.
Added more example animations in RenderTest with Global Pause/Resume button for Animations.

Jumar Macato 7 years ago
parent
commit
8dd3315c9a

+ 297 - 84
samples/RenderTest/Pages/AnimationsPage.xaml

@@ -1,97 +1,310 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <UserControl.Styles>
-        <Styles>
-          <Style Selector="Rectangle.Test">
-            <Setter Property="Margin" Value="15"/>
-            <Setter Property="Width" Value="100"/>
-            <Setter Property="Height" Value="100"/>
-          </Style>
-          <Style Selector="Border.Test">
-            <Setter Property="Margin" Value="15"/>
-            <Setter Property="Width" Value="100"/>
-            <Setter Property="Height" Value="100"/>
-          </Style>
-        <Style Selector="Rectangle.Rect1:pointerover">
-          <Style.Animations>
-            <Animation Duration="0:0:2.5" Easing="BounceEaseInOut">
-              <TransformKeyFrames Property="RotateTransform.Angle">
-                <KeyFrame Cue="0%" Value="0"/>
-                <KeyFrame Cue="100%" Value="360"/>
-              </TransformKeyFrames>
-            </Animation>
-          </Style.Animations>
-        </Style>
-        <Style Selector="Rectangle.Rect2:pointerover">
-          <Style.Animations>
-            <Animation Duration="0:0:0.5" Easing="SineEaseInOut">
-              <TransformKeyFrames Property="ScaleTransform.ScaleX">
-                <KeyFrame Cue="0%" Value="0.8"/>
-                <KeyFrame Cue="100%" Value="1"/>
-              </TransformKeyFrames>
-              <TransformKeyFrames Property="ScaleTransform.ScaleY">
-                <KeyFrame Cue="0%" Value="0.8"/>
-                <KeyFrame Cue="100%" Value="1"/>
-              </TransformKeyFrames>
-            </Animation>
-          </Style.Animations>
-        </Style>
-        <Style Selector="Rectangle.Rect3:pointerover">
-          <Style.Animations>
-            <Animation Duration="0:0:3" Easing="BounceEaseInOut">
-              <TransformKeyFrames Property="TranslateTransform.Y">
-                <KeyFrame Cue="0%" Value="0"/>
-                <KeyFrame Cue="48%" Value="-100"/>
-                <KeyFrame Cue="100%" Value="0"/>
-              </TransformKeyFrames>
-            </Animation>
-          </Style.Animations>
-        </Style>
-        <Style Selector="Border.Rect4:pointerover">
-          <Style.Animations>
-            <Animation Duration="0:0:3" Easing="CircularEaseInOut">
-              <TransformKeyFrames Property="SkewTransform.AngleX">
-                <KeyFrame Cue="0%" Value="0"/>
-                <KeyFrame Cue="25%" Value="-20"/>
-                <KeyFrame Cue="75%" Value="20"/>
-                <KeyFrame Cue="100%" Value="0"/>
-              </TransformKeyFrames>
-            </Animation>
-          </Style.Animations>
-        </Style>
-      </Styles>
+    <Styles>
+      <Styles.Resources>
+        <Template x:Key="Acorn">
+          <Path Fill="White" Stretch="Uniform" Data="F1 M 16.6309,18.6563C 17.1309,8.15625 29.8809,14.1563 29.8809,14.1563C 30.8809,11.1563 34.1308,11.4063 34.1308,11.4063C 33.5,12 34.6309,13.1563 34.6309,13.1563C 32.1309,13.1562 31.1309,14.9062 31.1309,14.9062C 41.1309,23.9062 32.6309,27.9063 32.6309,27.9062C 24.6309,24.9063 21.1309,22.1562 16.6309,18.6563 Z M 16.6309,19.9063C 21.6309,24.1563 25.1309,26.1562 31.6309,28.6562C 31.6309,28.6562 26.3809,39.1562 18.3809,36.1563C 18.3809,36.1563 18,38 16.3809,36.9063C 15,36 16.3809,34.9063 16.3809,34.9063C 16.3809,34.9063 10.1309,30.9062 16.6309,19.9063 Z"/>
+        </Template>        
+      </Styles.Resources>
+      <Style Selector="Border.Test">
+        <Setter Property="Margin" Value="15"/>
+        <Setter Property="Width" Value="100"/>
+        <Setter Property="Height" Value="100"/>
+        <Setter Property="Child" Value="{StaticResource Acorn}"/>
+      </Style>
+      <Style Selector="Border.Test">
+        <Setter Property="Margin" Value="15"/>
+        <Setter Property="Width" Value="100"/>
+        <Setter Property="Height" Value="100"/>
+      </Style>
+      <Style Selector="Border.Rect1:pointerover">
+        <Style.Animations>
+          <Animation Duration="0:0:2.5" Easing="QuinticEaseInOut">
+            <TransformKeyFrames Property="RotateTransform.Angle">
+              <KeyFrame Cue="0%" Value="0"/>
+              <KeyFrame Cue="100%" Value="360"/>
+            </TransformKeyFrames>
+          </Animation>
+        </Style.Animations>
+      </Style>
+      <Style Selector="Border.Rect2:pointerover">
+        <Style.Animations>
+          <Animation Duration="0:0:0.5" Easing="SineEaseInOut">
+            <TransformKeyFrames Property="ScaleTransform.ScaleX">
+              <KeyFrame Cue="0%" Value="0.8"/>
+              <KeyFrame Cue="100%" Value="1"/>
+            </TransformKeyFrames>
+            <TransformKeyFrames Property="ScaleTransform.ScaleY">
+              <KeyFrame Cue="0%" Value="0.8"/>
+              <KeyFrame Cue="100%" Value="1"/>
+            </TransformKeyFrames>
+          </Animation>
+        </Style.Animations>
+      </Style>
+      <Style Selector="Border.Rect3:pointerover">
+        <Style.Animations>
+          <Animation Duration="0:0:3" Easing="BounceEaseInOut">
+            <TransformKeyFrames Property="TranslateTransform.Y">
+              <KeyFrame Cue="0%" Value="0"/>
+              <KeyFrame Cue="48%" Value="-100"/>
+              <KeyFrame Cue="100%" Value="0"/>
+            </TransformKeyFrames>
+          </Animation>
+        </Style.Animations>
+      </Style>
+      <Style Selector="Border.Rect4:pointerover">
+        <Style.Animations>
+          <Animation Duration="0:0:3" Easing="CircularEaseInOut">
+            <TransformKeyFrames Property="SkewTransform.AngleX">
+              <KeyFrame Cue="0%" Value="0"/>
+              <KeyFrame Cue="25%" Value="-20"/>
+              <KeyFrame Cue="75%" Value="20"/>
+              <KeyFrame Cue="100%" Value="0"/>
+            </TransformKeyFrames>
+          </Animation>
+        </Style.Animations>
+      </Style>
+    </Styles>
   </UserControl.Styles>
-  <Grid> 
-    <StackPanel VerticalAlignment="Center" 
-                HorizontalAlignment="Center"
-                ClipToBounds="False">
-      <TextBlock HorizontalAlignment="Center">
-        Hover to activate Transform Keyframe Animations.
-      </TextBlock>
-      <StackPanel Orientation="Horizontal"
-          ClipToBounds="False">
-        <Rectangle Classes="Test Rect1" Fill="DarkRed">
-          <Rectangle.RenderTransform>
+  <Grid>
+    <StackPanel>
+      <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
+        <TextBlock VerticalAlignment="Center">
+          Hover to activate Transform Keyframe Animations.
+        </TextBlock>
+        <Button Content="{Binding PlayStateText}" Command="{Binding ToggleGlobalPlayState}"/>
+       </StackPanel>
+      <WrapPanel>
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
             <RotateTransform/>
-          </Rectangle.RenderTransform>
-        </Rectangle>
-        <Rectangle Classes="Test Rect2" Fill="DarkMagenta">
-          <Rectangle.RenderTransform>
+          </Border.RenderTransform>
+         </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
             <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
-          </Rectangle.RenderTransform>
-        </Rectangle>
-        <Rectangle Classes="Test Rect3" Fill="Navy">
-          <Rectangle.RenderTransform>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
             <TranslateTransform/>
-          </Rectangle.RenderTransform>
-        </Rectangle>
+          </Border.RenderTransform>
+        </Border>
         <Border Classes="Test Rect4" Background="SeaGreen">
           <Border.RenderTransform>
             <SkewTransform/>
           </Border.RenderTransform>
-            <Path Fill="White" Stretch="Uniform" Data="F1 M 16.6309,18.6563C 17.1309,8.15625 29.8809,14.1563 29.8809,14.1563C 30.8809,11.1563 34.1308,11.4063 34.1308,11.4063C 33.5,12 34.6309,13.1563 34.6309,13.1563C 32.1309,13.1562 31.1309,14.9062 31.1309,14.9062C 41.1309,23.9062 32.6309,27.9063 32.6309,27.9062C 24.6309,24.9063 21.1309,22.1562 16.6309,18.6563 Z M 16.6309,19.9063C 21.6309,24.1563 25.1309,26.1562 31.6309,28.6562C 31.6309,28.6562 26.3809,39.1562 18.3809,36.1563C 18.3809,36.1563 18,38 16.3809,36.9063C 15,36 16.3809,34.9063 16.3809,34.9063C 16.3809,34.9063 10.1309,30.9062 16.6309,19.9063 Z"/>          
-         </Border>
-      </StackPanel>
+        </Border>
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
+
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
 
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
+
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect2" Background="DarkMagenta">
+          <Border.RenderTransform>
+            <ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect3" Background="Navy" >
+          <Border.RenderTransform>
+            <TranslateTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect4" Background="SeaGreen">
+          <Border.RenderTransform>
+            <SkewTransform/>
+          </Border.RenderTransform>
+        </Border>
+        <Border Classes="Test Rect1" Background="DarkRed">
+          <Border.RenderTransform>
+            <RotateTransform/>
+          </Border.RenderTransform>
+        </Border>
+      </WrapPanel>
     </StackPanel>
   </Grid>
 </UserControl>

+ 2 - 0
samples/RenderTest/Pages/AnimationsPage.xaml.cs

@@ -7,6 +7,7 @@ using Avalonia.Data;
 using Avalonia.Input;
 using Avalonia.Markup.Xaml;
 using Avalonia.Media;
+using RenderTest.ViewModels;
 
 namespace RenderTest.Pages
 {
@@ -15,6 +16,7 @@ namespace RenderTest.Pages
         public AnimationsPage()
         {
             InitializeComponent();
+            this.DataContext = new AnimationsPageViewModel();
         }
 
         private void InitializeComponent()

+ 40 - 0
samples/RenderTest/ViewModels/AnimationsPageViewModel.cs

@@ -0,0 +1,40 @@
+using System;
+using ReactiveUI;
+using Avalonia.Animation;
+
+namespace RenderTest.ViewModels
+{
+    public class AnimationsPageViewModel : ReactiveObject
+    {
+        private string _playStateText = "Pause all animations";
+
+        public AnimationsPageViewModel()
+        {
+            ToggleGlobalPlayState = ReactiveCommand.Create(()=>TogglePlayState());
+        }
+
+        void TogglePlayState()
+        {
+            switch (Timing.GetGlobalPlayState())
+            {
+                case AnimationPlayState.Running:
+                    PlayStateText = "Resume all animations";
+                    Timing.SetGlobalPlayState(AnimationPlayState.Paused);
+                    break;
+
+                case AnimationPlayState.Paused:
+                    PlayStateText = "Pause all animations";
+                    Timing.SetGlobalPlayState(AnimationPlayState.Running);
+                    break;
+            }
+        }
+
+        public string PlayStateText
+        {
+            get { return _playStateText; }
+            set { this.RaiseAndSetIfChanged(ref _playStateText, value); }
+        }
+
+        public ReactiveCommand ToggleGlobalPlayState { get; }
+     }
+}

+ 8 - 1
src/Avalonia.Animation/Animatable.cs

@@ -31,6 +31,13 @@ namespace Avalonia.Animation
     /// </summary>
     public class Animatable : AvaloniaObject
     {
+        /// <summary>
+        /// Initializes this <see cref="Animatable"/> object.
+        /// </summary>
+        public Animatable()
+        {
+            Transitions = new Transitions.Transitions();
+        }
 
         /// <summary>
         /// Defines the <see cref="AnimationPlayState"/> property.
@@ -61,7 +68,7 @@ namespace Avalonia.Animation
         {
             get { return GetValue(TransitionsProperty); }
             set { SetValue(TransitionsProperty, value); }
-        }
+        } 
 
         /// <summary>
         /// Reacts to a change in a <see cref="AvaloniaProperty"/> value in 

+ 5 - 1
src/Avalonia.Animation/Keyframes/KeyFrames.cs

@@ -7,6 +7,7 @@ using Avalonia.Animation.Utils;
 using System.Reactive.Linq;
 using System.Linq;
 using Avalonia.Data;
+using System.Reactive.Disposables;
 
 namespace Avalonia.Animation.Keyframes
 {
@@ -36,8 +37,11 @@ namespace Avalonia.Animation.Keyframes
 
             return obsMatch
                 .Where(p => p == true)
+                .Where(p=> Timing.GetGlobalPlayState() != AnimationPlayState.Paused)
                 .Subscribe(_ =>
                 {
+ 
+
                     var interp = DoInterpolation(animation, control)
                                 .Select(p => (object)p);
                     control.Bind(Property, interp, BindingPriority.Animation);
@@ -115,7 +119,7 @@ namespace Avalonia.Animation.Keyframes
         /// </summary>
         public IObservable<(double Time, Animatable Target)> 
             SetupAnimation(Animation animation, Animatable control) =>
-                        Timing.GetTimer(control, animation.Duration, animation.Delay)
+                        Timing.GetAnimationsTimer(control, animation.Duration, animation.Delay)
                               .Select(t => (animation.Easing.Ease(t), control));
 
         /// <summary>

+ 79 - 18
src/Avalonia.Animation/Timing.cs

@@ -15,6 +15,9 @@ namespace Avalonia.Animation
     /// </summary>
     public static class Timing
     {
+        static ulong _animationsFrameCount, _transitionsFrameCount;
+        static AnimationPlayState _globalState = AnimationPlayState.Running;
+
         /// <summary>
         /// The number of frames per second.
         /// </summary>
@@ -25,55 +28,89 @@ namespace Avalonia.Animation
         /// </summary>
         private static readonly TimeSpan Tick = TimeSpan.FromSeconds(1.0 / FramesPerSecond);
 
-        static ulong _frameCount = 0;
-
         /// <summary>
         /// Initializes static members of the <see cref="Timing"/> class.
         /// </summary>
         static Timing()
         {
-            Stopwatch = new Stopwatch();
-            Stopwatch.Start();
-            Timer = Observable.Interval(Tick, AvaloniaScheduler.Instance)
+            AnimationTimer = Observable.Interval(Tick, AvaloniaScheduler.Instance)
                 .Select(_ =>
                 {
-                    _frameCount += 1;
-                    return _frameCount;
+                    switch (_globalState)
+                    {
+                        case AnimationPlayState.Paused:
+                            break;
+                        default:
+                            _animationsFrameCount += 1;
+                            break;
+                    }
+                    return _animationsFrameCount;
                 })
                 .Publish()
                 .RefCount();
+
+            TransitionsTimer = Observable.Interval(Tick, AvaloniaScheduler.Instance)
+                               .Select(p => _transitionsFrameCount += 1)
+                               .Publish()
+                               .RefCount();
+        }
+
+
+        /// <summary>
+        /// Sets the animation play state for all animations
+        /// </summary>
+        public static void SetGlobalPlayState(AnimationPlayState playState)
+        {
+            Dispatcher.UIThread.VerifyAccess();
+            _globalState = playState;
+        }
+
+        /// <summary>
+        /// Gets the animation play state for all animations
+        /// </summary>
+        public static AnimationPlayState GetGlobalPlayState()
+        {
+            Dispatcher.UIThread.VerifyAccess();
+            return _globalState;
         }
 
         /// <summary>
-        /// The stopwatch used to track time.
+        /// Gets the animation timer.
         /// </summary>
+        /// <remarks>
+        /// The animation timer increments usually 60 times per second as
+        /// defined in <see cref="FramesPerSecond"/>.
+        /// The parameter passed to a subsciber is the number of frames since the animation system was
+        /// initialized.
+        /// </remarks>
         /// <value>
-        /// The stopwatch used to track time.
+        /// The animation timer.
         /// </value>
-        public static Stopwatch Stopwatch
+        public static IObservable<ulong> AnimationTimer
         {
             get;
         }
 
         /// <summary>
-        /// Gets the animation timer.
+        /// Gets the transitions timer.
         /// </summary>
         /// <remarks>
-        /// The animation timer ticks <see cref="FramesPerSecond"/> times per second. The
-        /// parameter passed to a subsciber is the number of frames since the animation system was
+        /// The transitions timer increments usually 60 times per second as
+        /// defined in <see cref="FramesPerSecond"/>.
+        /// The parameter passed to a subsciber is the number of frames since the animation system was
         /// initialized.
         /// </remarks>
         /// <value>
         /// The animation timer.
         /// </value>
-        public static IObservable<ulong> Timer
+        public static IObservable<ulong> TransitionsTimer
         {
             get;
         }
 
-
         /// <summary>
         /// Gets a timer that fires every frame for the specified duration with delay.
+        /// This timer's running state can be changed via <see cref="SetGlobalPlayState"/> method.
         /// </summary>
         /// <returns>
         /// An observable that notifies the subscriber of the progress along the animation.
@@ -83,12 +120,36 @@ namespace Avalonia.Animation
         /// 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.
         /// </remarks>
-        public static IObservable<double> GetTimer(Animatable control, TimeSpan duration, TimeSpan delay)
+        public static IObservable<double> GetAnimationsTimer(Animatable control, TimeSpan duration, TimeSpan delay)
         {
-            var startTime = _frameCount;
+            var startTime = _animationsFrameCount;
             var _duration = (ulong)(duration.Ticks/Tick.Ticks);
             var endTime = startTime + _duration;
-            return Timer
+            return AnimationTimer
+                .TakeWhile(x => x < endTime)
+                .Select(x => (double)(x - startTime) / _duration)
+                .StartWith(0.0)
+                .Concat(Observable.Return(1.0));
+        }
+
+        /// <summary>
+        /// Gets a timer that fires every frame for the specified duration with delay.
+        /// </summary>
+        /// <returns>
+        /// An observable that notifies the subscriber of the progress along the transition.
+        /// </returns>
+        /// <remarks>
+        /// The parameter passed to the subscriber is the progress along the transition, 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.
+        /// </remarks>
+        public static IObservable<double> GetTransitionsTimer(Animatable control, TimeSpan duration, TimeSpan delay)
+        {
+            var startTime = _transitionsFrameCount;
+            var _duration = (ulong)(duration.Ticks / Tick.Ticks);
+            var endTime = startTime + _duration;
+
+            return TransitionsTimer
                 .TakeWhile(x => x < endTime)
                 .Select(x => (double)(x - startTime) / _duration)
                 .StartWith(0.0)

+ 1 - 1
src/Avalonia.Animation/Transitions/Transition.cs

@@ -61,7 +61,7 @@ namespace Avalonia.Animation.Transitions
         /// <inheritdocs/>
         public IDisposable Apply(Animatable control, object oldValue, object newValue)
         {
-            var transition = DoTransition(Timing.GetTimer(control, Duration, TimeSpan.Zero), (T)oldValue, (T)newValue).Select(p => (object)p);
+            var transition = DoTransition(Timing.GetTransitionsTimer(control, Duration, TimeSpan.Zero), (T)oldValue, (T)newValue).Select(p => (object)p);
             return control.Bind(Property, transition, Data.BindingPriority.Animation);
         }