/// <summary>
        /// Animates the offset of the UIElement.
        /// </summary>
        /// <param name="animationSet">The animation set.</param>
        /// <param name="offsetX">The offset on the x axis.</param>
        /// <param name="offsetY">The offset on the y axis.</param>
        /// <param name="duration">The duration in milliseconds.</param>
        /// <param name="delay">The delay in milliseconds. (ignored if duration == 0)</param>
        /// <param name="easingType">Used to describe how the animation interpolates between keyframes.</param>
        /// <param name="easingMode">The EasingMode to use to interpolate between keyframes.</param>
        /// <returns>
        /// An AnimationSet.
        /// </returns>
        public static AnimationSet Offset(
            this AnimationSet animationSet,
            float offsetX         = 0f,
            float offsetY         = 0f,
            double duration       = 500d,
            double delay          = 0d,
            EasingType easingType = EasingType.Default,
            EasingMode easingMode = EasingMode.EaseOut)
        {
            if (animationSet == null)
            {
                return(null);
            }

            if (!AnimationSet.UseComposition)
            {
                var element   = animationSet.Element;
                var transform = GetAttachedCompositeTransform(element);

                var animationX = new DoubleAnimation();
                var animationY = new DoubleAnimation();

                animationX.To = offsetX;
                animationY.To = offsetY;

                animationX.Duration       = animationY.Duration = TimeSpan.FromMilliseconds(duration);
                animationX.BeginTime      = animationY.BeginTime = TimeSpan.FromMilliseconds(delay);
                animationX.EasingFunction = animationY.EasingFunction = GetEasingFunction(easingType, easingMode);

                animationSet.AddStoryboardAnimation(GetAnimationPath(transform, element, "TranslateX"), animationX);
                animationSet.AddStoryboardAnimation(GetAnimationPath(transform, element, "TranslateY"), animationY);
            }
            else
            {
                var visual       = animationSet.Visual;
                var offsetVector = new Vector3(offsetX, offsetY, 0);

                if (duration <= 0)
                {
                    animationSet.AddCompositionDirectPropertyChange("Offset", offsetVector);
                    return(animationSet);
                }

                var compositor = visual?.Compositor;

                if (compositor == null)
                {
                    return(null);
                }

                var animation = compositor.CreateVector3KeyFrameAnimation();
                animation.Duration  = TimeSpan.FromMilliseconds(duration);
                animation.DelayTime = TimeSpan.FromMilliseconds(delay);
                animation.InsertKeyFrame(1f, offsetVector, GetCompositionEasingFunction(easingType, compositor, easingMode));

                animationSet.AddCompositionAnimation("Offset", animation);
            }

            return(animationSet);
        }
        /// <summary>
        /// Animates the rotation in degrees of the the UIElement.
        /// </summary>
        /// <param name="animationSet">The animation set.</param>
        /// <param name="value">The value in degrees to rotate.</param>
        /// <param name="centerX">The center x in pixels.</param>
        /// <param name="centerY">The center y in pixels.</param>
        /// <param name="duration">The duration in milliseconds.</param>
        /// <param name="delay">The delay in milliseconds. (ignored if duration == 0)</param>
        /// <param name="easingType">Used to describe how the animation interpolates between keyframes.</param>
        /// <returns>
        /// An AnimationSet.
        /// </returns>
        public static AnimationSet Rotate(
            this AnimationSet animationSet,
            float value           = 0f,
            float centerX         = 0f,
            float centerY         = 0f,
            double duration       = 500d,
            double delay          = 0d,
            EasingType easingType = EasingType.Default)
        {
            if (animationSet == null)
            {
                return(null);
            }

            if (!AnimationSet.UseComposition)
            {
                var element   = animationSet.Element;
                var transform = GetAttachedCompositeTransform(element);

                transform.CenterX = centerX;
                transform.CenterY = centerY;

                var animation = new DoubleAnimation
                {
                    To             = value,
                    Duration       = TimeSpan.FromMilliseconds(duration),
                    BeginTime      = TimeSpan.FromMilliseconds(delay),
                    EasingFunction = GetEasingFunction(easingType)
                };

                animationSet.AddStoryboardAnimation(GetAnimationPath(transform, element, "Rotation"), animation);
            }
            else
            {
                var visual = animationSet.Visual;
                visual.CenterPoint = new Vector3(centerX, centerY, 0);

                if (duration <= 0)
                {
                    animationSet.AddCompositionDirectPropertyChange("RotationAngleInDegrees", value);
                    return(animationSet);
                }

                var compositor = visual.Compositor;

                if (compositor == null)
                {
                    return(null);
                }

                var animation = compositor.CreateScalarKeyFrameAnimation();
                animation.Duration  = TimeSpan.FromMilliseconds(duration);
                animation.DelayTime = TimeSpan.FromMilliseconds(delay);
                animation.InsertKeyFrame(1f, value);

                animationSet.AddCompositionAnimation("RotationAngleInDegrees", animation);
            }

            return(animationSet);
        }
        /// <summary>
        /// Animates the opacity of the the UIElement.
        /// </summary>
        /// <param name="animationSet">The animation set.</param>
        /// <param name="value">The fade value, between 0 and 1.</param>
        /// <param name="duration">The duration in milliseconds.</param>
        /// <param name="delay">The delay. (ignored if duration == 0)</param>
        /// <param name="easingType">Used to describe how the animation interpolates between keyframes.</param>
        /// <returns>
        /// An AnimationSet.
        /// </returns>
        public static AnimationSet Fade(
            this AnimationSet animationSet,
            float value           = 0f,
            double duration       = 500d,
            double delay          = 0d,
            EasingType easingType = EasingType.Default)
        {
            if (animationSet == null)
            {
                return(null);
            }

            if (!AnimationSet.UseComposition)
            {
                var animation = new DoubleAnimation
                {
                    To             = value,
                    Duration       = TimeSpan.FromMilliseconds(duration),
                    BeginTime      = TimeSpan.FromMilliseconds(delay),
                    EasingFunction = GetEasingFunction(easingType)
                };

                animationSet.AddStoryboardAnimation("Opacity", animation);
            }
            else
            {
                if (duration <= 0)
                {
                    animationSet.AddCompositionDirectPropertyChange("Opacity", value);
                    return(animationSet);
                }

                var visual = animationSet.Visual;

                var compositor = visual?.Compositor;

                if (compositor == null)
                {
                    return(null);
                }

                var animation = compositor.CreateScalarKeyFrameAnimation();
                animation.Duration  = TimeSpan.FromMilliseconds(duration);
                animation.DelayTime = TimeSpan.FromMilliseconds(delay);
                if (easingType == EasingType.Default)
                {
                    animation.InsertKeyFrame(1f, value);
                }
                else
                {
                    animation.InsertKeyFrame(1f, value, GetCompositionEasingFunction(easingType, compositor));
                }

                animationSet.AddCompositionAnimation("Opacity", animation);
            }

            return(animationSet);
        }
        /// <summary>
        /// Animates the scale of the the specified UIElement.
        /// </summary>
        /// <param name="animationSet">The animationSet object.</param>
        /// <param name="scaleX">The scale on the x axis.</param>
        /// <param name="scaleY">The scale on the y axis.</param>
        /// <param name="centerX">The center x in pixels.</param>
        /// <param name="centerY">The center y in pixels.</param>
        /// <param name="duration">The duration in milliseconds.</param>
        /// <param name="delay">The delay in milliseconds. (ignored if duration == 0)</param>
        /// <returns>
        /// An AnimationSet.
        /// </returns>
        public static AnimationSet Scale(
            this AnimationSet animationSet,
            float scaleX    = 1f,
            float scaleY    = 1f,
            float centerX   = 0f,
            float centerY   = 0f,
            double duration = 500d,
            double delay    = 0d)
        {
            if (animationSet == null)
            {
                return(null);
            }

            if (!AnimationSet.UseComposition)
            {
                var element   = animationSet.Element;
                var transform = GetAttachedCompositeTransform(element);

                transform.CenterX = centerX;
                transform.CenterY = centerY;

                var animationX = new DoubleAnimation();
                var animationY = new DoubleAnimation();

                animationX.To = scaleX;
                animationY.To = scaleY;

                animationX.Duration       = animationY.Duration = TimeSpan.FromMilliseconds(duration);
                animationX.BeginTime      = animationY.BeginTime = TimeSpan.FromMilliseconds(delay);
                animationX.EasingFunction = animationY.EasingFunction = _defaultStoryboardEasingFunction;

                animationSet.AddStoryboardAnimation(GetAnimationPath(transform, element, "ScaleX"), animationX);
                animationSet.AddStoryboardAnimation(GetAnimationPath(transform, element, "ScaleY"), animationY);
            }
            else
            {
                var visual = animationSet.Visual;
                visual.CenterPoint = new Vector3(centerX, centerY, 0);
                var scaleVector = new Vector3(scaleX, scaleY, 1.0f);

                if (duration <= 0)
                {
                    animationSet.AddCompositionDirectPropertyChange("Scale", scaleVector);
                    return(animationSet);
                }

                var compositor = visual.Compositor;

                if (compositor == null)
                {
                    return(null);
                }

                var animation = compositor.CreateVector3KeyFrameAnimation();
                animation.Duration  = TimeSpan.FromMilliseconds(duration);
                animation.DelayTime = TimeSpan.FromMilliseconds(delay);
                animation.InsertKeyFrame(1f, scaleVector);

                animationSet.AddCompositionAnimation("Scale", animation);
            }

            return(animationSet);
        }