Example #1
0
        /// <summary>
        /// Animates the tiles using the supplied entrance mode, Y direction, Z direction and duration.
        /// </summary>
        /// <param name="mode">The entrance mode (Enter or Exit).</param>
        /// <param name="yDirection">The direction of the animation in the vertical axis (TopToBottom or BottomToTop)</param>
        /// <param name="zDirection">The direction of the animation in the depth axis (FrontToBack or BackToFront)</param>
        /// <param name="duration">The duration of the animation for each tile</param>
        public void AnimateTiles(EnterMode mode, YDirection yDirection, ZDirection zDirection, TimeSpan duration)
        {
            // If the control has not been rendered, cancel the animation
            if (ActualWidth <= 0 || ActualHeight <= 0)
            {
                return;
            }

            // If the control it's empty, after position calculation is ran, cancel the animation
            CalculateElementPositions();
            if (_positions == null || _positions.Count <= 0)
            {
                return;
            }

            // Calculates start and end heights
            double startHeight = 0;
            double endHeight = ActualHeight;

            startHeight = 0;
            endHeight = _scrollViewer.ViewportHeight;

            // Get the visible tiles for the current configuration
            // Tiles that are partially visible are also counted
            var visibleTiles = _positions.Where(x => x.Value.Y + x.Key.ActualHeight >= startHeight && x.Value.Y <= startHeight + endHeight);

            // No visible tiles, do nothing
            var visibleCount = visibleTiles.Count();
            if (visibleCount <= 0)
            {
                return;
            }

            // The Y coordinate of the lowest element is useful
            // when we animate from bottom to top
            double lowestY = visibleTiles.Max(el => el.Value.Y);

            // Store the animations to group them in one Storyboard in the end
            var animations = new List<Timeline>();
            var lastAnimations = new List<Timeline>();

            foreach (var tilePosition in visibleTiles)
            {
                var currentTileAnimationDuration = duration;
                bool isTileSelected = tilePosition.Key.DataContext == SelectedItem;
                if (isTileSelected)
                {
                    currentTileAnimationDuration
                        = currentTileAnimationDuration.Multiply(0.8d);
                }

                var tile = tilePosition.Key;
                var position = tilePosition.Value;
                var projection = tile.Projection as PlaneProjection;
                double rotationFrom, rotationTo, opacityTo;

                // Reset all children's opacity regardless of their animations
                if (mode == EnterMode.Exit)
                {
                    tile.Opacity = 1;
                    opacityTo = 0;
                    rotationFrom = 0;
                    rotationTo = zDirection == ZDirection.BackToFront ? -90 : 90;
                }
                else
                {
                    tile.Opacity = 0;
                    opacityTo = 1;
                    rotationFrom = zDirection == ZDirection.BackToFront ? -90 : 90;
                    rotationTo = 0;
                }

                // Used to determine begin time - depends if we're moving from bottom or from top
                double relativeY;

                if (yDirection == YDirection.BottomToTop)
                {
                    // The lowest element should have relativeY == 0
                    relativeY = lowestY - position.Y;
                }
                else
                {
                    relativeY = position.Y;
                }

                var easing = new QuadraticEase() { EasingMode = EasingMode.EaseInOut };

                var rotationAnimation = new DoubleAnimation { From = rotationFrom, To = rotationTo, EasingFunction = easing };
                rotationAnimation.Duration = currentTileAnimationDuration;
                if (isTileSelected)
                {
                    //animate tile as it's lower than all others (so it will be later even it's last in the list)
                    rotationAnimation.BeginTime =
                           currentTileAnimationDuration.Multiply(GetBeginTimeFactor(position.X, lowestY * 1.2d, mode));
                }
                else
                {
                    rotationAnimation.BeginTime =
                        currentTileAnimationDuration.Multiply(GetBeginTimeFactor(position.X, relativeY, mode));
                }
                rotationAnimation.SetTargetAndProperty(projection, PlaneProjection.RotationYProperty);

                var opacityAnimation = new DoubleAnimation { To = opacityTo, EasingFunction = easing };
                // The opacity animation takes the last 60% of the rotation animation
                opacityAnimation.Duration = currentTileAnimationDuration.Multiply(0.6);
                opacityAnimation.BeginTime = rotationAnimation.BeginTime;
                if (mode == EnterMode.Exit)
                    opacityAnimation.BeginTime += currentTileAnimationDuration - opacityAnimation.Duration.TimeSpan;
                opacityAnimation.SetTargetAndProperty(tile, UIElement.OpacityProperty);

                animations.Add(rotationAnimation);
                animations.Add(opacityAnimation);
            }
            animations.AddRange(lastAnimations);

            // Begin all animations
            var sb = new Storyboard();

            foreach (var a in animations)
            {
                sb.Children.Add(a);
            }

            sb.SpeedRatio = SpeedRatio;
            sb.Completed += sb_Completed;
            sb.Begin();
        }
Example #2
0
        private void AnimateTiles(EnterMode mode, XDirection xDirection, ZDirection zDirection, TimeSpan duration, Action callback)
        {
            // If the control has not been rendered or it's empty, cancel the animation
            if (this.ActualWidth <= 0 || this.ActualHeight <= 0 || this._positions == null || this._positions.Count <= 0) return;

            // Get the visible tiles for the current configuration
            // Tiles that are partially visible are also counted
            var visibleitems = this._positions.Where(x => x.Value.X + x.Key.ActualWidth >= 0 && x.Value.X <= this.ActualWidth &&
                                                     x.Value.Y + x.Key.ActualHeight >= 0 && x.Value.Y <= this.ActualHeight);

            // No visible tiles, do nothing
            if (visibleitems.Count() <= 0) return;

            // The Y coordinate of the lowest element is useful 
            // when we animate from bottom to top
            double lowestX = visibleitems.Max(el => el.Value.X);

            // Store the animations to group them in one Storyboard in the end
            var animations = new List<Timeline>();

            foreach (var tilePosition in visibleitems)
            {
                // To make syntax lighter
                var tile = tilePosition.Key;
                var position = tilePosition.Value;
                var projection = tile.Projection as PlaneProjection;

                double rotationFrom, rotationTo, opacityTo;

                // Reset all children's opacity regardless of their animations
                if (mode == EnterMode.Exit)
                {
                    tile.Opacity = 1;
                    opacityTo = 0;
                    rotationFrom = 0;
                    rotationTo = zDirection == ZDirection.BackToFront ? -90 : 90;
                }
                else
                {
                    tile.Opacity = 0;
                    opacityTo = 1;
                    rotationFrom = zDirection == ZDirection.BackToFront ? -90 : 90;
                    rotationTo = 0;
                }

                // Used to determine begin time - depends if we're moving from bottom or from top
                double relativeX;

                if (xDirection == XDirection.LeftToRight)
                {
                    // The lowest element should have relativeY == 0
                    relativeX = lowestX - position.X;
                }
                else
                {
                    relativeX = position.X;
                }

                var easing = new QuadraticEase() { EasingMode = EasingMode.EaseInOut };

                var rotationAnimation = new DoubleAnimation { From = rotationFrom, To = rotationTo, EasingFunction = easing };
                rotationAnimation.Duration = duration;
                rotationAnimation.BeginTime = duration.Multiply(this.GetBeginTimeFactorFavorite(relativeX, position.Y, mode));
                rotationAnimation.SetTargetAndProperty(projection, PlaneProjection.RotationYProperty);

                var opacityAnimation = new DoubleAnimation { To = opacityTo, EasingFunction = easing };
                // The opacity animation takes the last 60% of the rotation animation
                opacityAnimation.Duration = duration.Multiply(0.6);
                opacityAnimation.BeginTime = rotationAnimation.BeginTime;
                if (mode == EnterMode.Exit)
                    opacityAnimation.BeginTime += duration - opacityAnimation.Duration.TimeSpan;
                opacityAnimation.SetTargetAndProperty(tile, UIElement.OpacityProperty);

                animations.Add(rotationAnimation);
                animations.Add(opacityAnimation);
            }

            // Begin all animations
            var sb = new Storyboard();
            sb.Completed += (sender, args) =>
            {
                if (callback != null)
                {
                    callback();
                }
            };

            foreach (var a in animations)
                sb.Children.Add(a);
            sb.Begin();
        }