Пример #1
0
        /// <summary>
        /// Performs the animation specified in the options
        /// </summary>
        /// <param name="options">animation options</param>
        /// <returns>an async task</returns>
        public static async Task AnimateAsync(AnimatorOptions options)
        {
            if (options.DelayProvider == null && Time.CurrentTime != null)
            {
                options.DelayProvider = Time.CurrentTime;
            }
            else if (options.DelayProvider == null)
            {
                options.DelayProvider = new WallClockDelayProvider();
            }

            var originalFrom = options.From;
            var originalTo   = options.To;

            try
            {
                var i = 0;
                while (i == 0 || (options.Loop != null && options.Loop.IsExpired == false))
                {
                    i++;
                    await AnimateAsyncInternal(options);

                    if (options.AutoReverse)
                    {
                        if (options.AutoReverseDelay > 0)
                        {
                            await options.DelayProvider.DelayAsync(TimeSpan.FromMilliseconds(options.AutoReverseDelay));
                        }

                        var temp = options.From;
                        options.From = options.To;
                        options.To   = temp;
                        options.OnReversedChanged?.Invoke(true);
                        await AnimateAsyncInternal(options);

                        if (options.AutoReverseDelay > 0)
                        {
                            await options.DelayProvider.DelayAsync(TimeSpan.FromMilliseconds(options.AutoReverseDelay));
                        }

                        options.From = originalFrom;
                        options.To   = originalTo;
                        options.OnReversedChanged?.Invoke(false);
                    }
                }
            }
            finally
            {
                options.From = originalFrom;
                options.To   = originalTo;
            }
        }
Пример #2
0
        private static async Task AnimateAsyncInternal(AnimatorOptions options)
        {
            var animationTime = TimeSpan.FromMilliseconds(options.Duration);

            if (animationTime == TimeSpan.Zero)
            {
#if DEBUG
                options.Debug?.Invoke("NoOp animation");
#endif

                options.Set(options.To);
            }

            var numberOfFrames = (float)(ConsoleMath.Round(animationTime.TotalSeconds * TargetFramesPerSecond));
            numberOfFrames = Math.Max(numberOfFrames, 2);
#if DEBUG
            options.Debug?.Invoke($"Frames: {numberOfFrames}");
#endif
            var timeBetweenFrames = TimeSpan.FromMilliseconds(ConsoleMath.Round(animationTime.TotalMilliseconds / numberOfFrames));
#if DEBUG
            options.Debug?.Invoke($"Time between frames: {timeBetweenFrames.TotalMilliseconds} ms");
#endif
            var initialValue = options.From;
            options.Set(initialValue);
#if DEBUG
            options.Debug?.Invoke($"InitialValue: {initialValue}");
#endif
            var delta = options.To - initialValue;
#if DEBUG
            options.Debug?.Invoke($"Delta: {delta}");
#endif
            var workSw = Stopwatch.StartNew();
            for (float i = 1; i <= numberOfFrames; i++)
            {
                var percentageDone = i / numberOfFrames;
                if (options.EasingFunction != null)
                {
                    percentageDone = options.EasingFunction(percentageDone);
                }

                var scheduledTimeAfterThisFrame = TimeSpan.FromMilliseconds(timeBetweenFrames.TotalMilliseconds * i);
                var newValue = initialValue + (delta * percentageDone);
                options.OnSet?.Invoke(percentageDone);
                options.Set(newValue);
#if DEBUG
                options.Debug?.Invoke($"Set value to {newValue} at percentage {percentageDone}");
#endif
                var delayTime = options.DelayProvider is WallClockDelayProvider?TimeSpan.FromMilliseconds(Math.Max(0, scheduledTimeAfterThisFrame.TotalMilliseconds - workSw.Elapsed.TotalMilliseconds)) : timeBetweenFrames;

#if DEBUG
                options.Debug?.Invoke($"Delayed for {delayTime.TotalMilliseconds} ms at percentage {percentageDone}");
#endif

                if (options.IsCancelled != null && options.IsCancelled())
                {
                    return;
                }
                if (delayTime == TimeSpan.Zero)
                {
                    await options.YieldAsync();
                }
                else
                {
                    await options.DelayAsync(delayTime);
                }
            }
        }