예제 #1
0
        private void ScrollToVerticalOffset(double delta, bool isAnimationEnabled)
        {
            var scrollViewer = this.GetScrollViewer();

            if (scrollViewer == null)
            {
                return;
            }

            var time = this.AnimationTime;

            if (time <= 0 || !isAnimationEnabled)
            {
                // no animation
                scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + delta);
                return;
            }

            var animation = new DoubleAnimation()
            {
                From           = 0,
                To             = delta,
                EasingFunction = new PowerEase()
                {
                    EasingMode = EasingMode.EaseInOut, Power = 1.2
                },
                Duration = new Duration(TimeSpan.FromMilliseconds(time)),
            };

            var target = new SingleValueAnimator <double>();

            var id = this.idCount++;

            target.ValueChanged += (o, e) => this.Animated(scrollViewer, id, target, e);

            //var startTime = DateTime.Now.Ticks;

            animation.Completed += (o, e) =>
            {
                //Debug.WriteLine(DateTime.Now.Ticks - startTime);
                this.animatingObjects.Remove(id);
            };

            //Debug.WriteLine($"{DateTime.Now.Ticks}, {this.animatingObjects.Count}");

            target.BeginAnimation(SingleValueAnimator <double> .ValueProperty, animation);
        }
예제 #2
0
        /// <summary>
        /// アニメーション中
        /// </summary>
        /// <param name="scrollViewer"></param>
        /// <param name="id"></param>
        /// <param name="e"></param>
        private void Animated
            (ScrollViewer scrollViewer, int id, SingleValueAnimator <double> target,
            DependencyPropertyChangedEventArgs e)
        {
            this.request.Enqueue(new ScrollRequestContainer()
            {
                OldValue = (double)e.OldValue,
                NewValue = (double)e.NewValue,
                Id       = id,
            });

            this.animatingObjects[id] = target;

            //リクエストが溜まっていない間はスクロールしない
            if (request.Count < this.animatingObjects.Count)
            {
                //Debug.WriteLine($"request:{request.Count},animating:{this.animatingObjects.Count}");
                return;
            }

            var items = this.request.ToArray();

            this.request.Clear();

            var oldValue = 0.0;
            var newValue = 0.0;

            foreach (var item in items)
            {
                oldValue += item.OldValue;
                newValue += item.NewValue;
            }
            //var oldValue = items.Sum(x => x.OldValue);
            //var newValue = items.Sum(x => x.NewValue);

            var ids = items.Select(x => x.Id).Distinct().ToArray();

            if (this.prevActedIds != null)
            {
                //動いていないアニメーションが検出された

                var actedIds = this.prevActedIds.Concat(ids).Distinct().ToArray();


                this.animatingObjects
                .Where(x => !actedIds.Contains(x.Key))
                .ToArray()
                .ForEach(x =>
                {
                    this.animatingObjects.Remove(x.Key);
                    Debug.WriteLine($"aborted animation is detected:{x.Key}");
                });

                this.prevActedIds = null;
            }
            else
            {
                if (ids.Length != items.Length)
                {
                    //Id被り=動いていないアニメーションがある
                    this.prevActedIds = ids;
                    Debug.WriteLine("animation id is repeated");
                }
                else
                {
                    this.prevActedIds = null;
                }
            }


            var b = scrollViewer.VerticalOffset - oldValue;

            scrollViewer.ScrollToVerticalOffset(b + newValue);
            //Debug.WriteLine($"{DateTime.Now.Ticks}, {newValue - oldValue}, {items.Length}");
        }