diff --git a/LottieUWP.Sample/MainPage.xaml b/LottieUWP.Sample/MainPage.xaml
index b9f1e3f..5a89573 100644
--- a/LottieUWP.Sample/MainPage.xaml
+++ b/LottieUWP.Sample/MainPage.xaml
@@ -34,7 +34,7 @@
-
+
diff --git a/LottieUWP/LottieAnimationView.cs b/LottieUWP/LottieAnimationView.cs
index 08e60e0..727cd6a 100644
--- a/LottieUWP/LottieAnimationView.cs
+++ b/LottieUWP/LottieAnimationView.cs
@@ -550,6 +550,7 @@ public virtual LottieComposition Composition
ImageDrawable = _lottieDrawable;
_composition = value;
+ FrameRate = _composition.FrameRate;
InvalidateArrange();
InvalidateMeasure();
@@ -769,20 +770,20 @@ private static void RepeatCountPropertyChangedCallback(DependencyObject dependen
lottieAnimationView._lottieDrawable.RepeatCount = (int)e.NewValue;
}
- public int TargetFps
+ public float FrameRate
{
- get { return (int)GetValue(TargetFpsProperty); }
- set { SetValue(TargetFpsProperty, value); }
+ get { return (float)GetValue(FrameRateProperty); }
+ set { SetValue(FrameRateProperty, value); }
}
// Using a DependencyProperty as the backing store for RepeatCount. This enables animation, styling, binding, etc...
- public static readonly DependencyProperty TargetFpsProperty =
- DependencyProperty.Register("TargetFps", typeof(int), typeof(LottieAnimationView), new PropertyMetadata(60, TargetFpsPropertyChangedCallback));
+ public static readonly DependencyProperty FrameRateProperty =
+ DependencyProperty.Register("FrameRate", typeof(float), typeof(LottieAnimationView), new PropertyMetadata(60f, FrameRatePropertyChangedCallback));
- private static void TargetFpsPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
+ private static void FrameRatePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
if (dependencyObject is LottieAnimationView lottieAnimationView)
- lottieAnimationView._lottieDrawable.TargetFps = (int)e.NewValue;
+ lottieAnimationView._lottieDrawable.FrameRate = (float)e.NewValue;
}
public virtual bool IsAnimating => _lottieDrawable.IsAnimating;
diff --git a/LottieUWP/LottieDrawable.cs b/LottieUWP/LottieDrawable.cs
index 642e7b2..fc62fbe 100644
--- a/LottieUWP/LottieDrawable.cs
+++ b/LottieUWP/LottieDrawable.cs
@@ -598,10 +598,10 @@ public int RepeatCount
get => _animator.RepeatCount;
}
- public int TargetFps
+ public float FrameRate
{
- get => _animator.TargetFps;
- set => _animator.TargetFps = value;
+ get => _animator.FrameRate;
+ set => _animator.FrameRate = value;
}
public virtual bool IsAnimating => _animator.IsRunning;
diff --git a/LottieUWP/Utils/LottieValueAnimator.cs b/LottieUWP/Utils/LottieValueAnimator.cs
index 7287ea3..216669b 100644
--- a/LottieUWP/Utils/LottieValueAnimator.cs
+++ b/LottieUWP/Utils/LottieValueAnimator.cs
@@ -16,8 +16,9 @@ public class LottieValueAnimator : BaseLottieAnimator
private float _minFrame = int.MinValue;
private float _maxFrame = int.MaxValue;
private LottieComposition _composition;
+ private float _frameRate;
protected bool _isRunning;
-
+
///
/// Returns a float representing the current value of the animation from 0 to 1
/// regardless of the animation speed, direction, or min and max frames.
@@ -96,15 +97,17 @@ public override void DoFrame()
long timeSinceFrame = now - _frameTime;
float frameDuration = FrameDurationNs;
float frames = timeSinceFrame / frameDuration;
- if (frames == 0)
+ int wholeFrames = (int)frames;
+ if (wholeFrames == 0)
{
return;
}
- _frame += IsReversed ? -frames : frames;
+ _frame += IsReversed ? -wholeFrames : wholeFrames;
bool ended = !MiscUtils.Contains(_frame, MinFrame, MaxFrame);
_frame = MiscUtils.Clamp(_frame, MinFrame, MaxFrame);
- _frameTime = now;
+ float partialFramesDuration = (frames - wholeFrames) * frameDuration;
+ _frameTime = (long)(now - partialFramesDuration);
Debug.WriteLineIf(LottieLog.TraceEnabled, $"Tick milliseconds: {timeSinceFrame}", LottieLog.Tag);
@@ -148,11 +151,22 @@ private float FrameDurationNs
}
}
+ public override float FrameRate
+ {
+ get => _frameRate;
+ set
+ {
+ _frameRate = value <= 1000 ? (value > 1 ? value : 1) : 1000;
+ UpdateTimerInterval();
+ }
+ }
+
public LottieComposition Composition
{
set
{
_composition = value;
+ FrameRate = _composition.FrameRate;
_frame = MinFrame;
_frameTime = SystemnanoTime();
}
diff --git a/LottieUWP/ValueAnimator.cs b/LottieUWP/ValueAnimator.cs
index 8ce4ae7..40f3e6d 100644
--- a/LottieUWP/ValueAnimator.cs
+++ b/LottieUWP/ValueAnimator.cs
@@ -36,17 +36,8 @@ public void RemoveAllListeners()
private IInterpolator _interpolator;
private Timer _timer;
- private int _targetFps = 60;
- public int TargetFps
- {
- get => _targetFps;
- set
- {
- _targetFps = value <= 1000 ? (value > 1 ? value : 1) : 1000;
- _timer?.Change(TimeSpan.Zero, GetTimerInterval());
- }
- }
+ public abstract float FrameRate { get; set; }
protected virtual void OnValueChanged()
{
@@ -85,9 +76,14 @@ protected void PrivateStart()
}
}
+ protected void UpdateTimerInterval()
+ {
+ _timer?.Change(TimeSpan.Zero, GetTimerInterval());
+ }
+
private TimeSpan GetTimerInterval()
{
- return TimeSpan.FromTicks((long)Math.Floor((decimal)TimeSpan.TicksPerSecond / TargetFps));
+ return TimeSpan.FromTicks((long)Math.Floor(TimeSpan.TicksPerSecond / (decimal)FrameRate));
}
protected virtual void RemoveFrameCallback()