using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Text; using System.Threading.Tasks; using Windows.UI.Composition; using Windows.UI.Xaml; using Windows.UI.Xaml.Hosting; namespace Wino.Extensions { public static partial class CompositionExtensions { public static void EnableFluidVisibilityAnimation(this UIElement element, AnimationAxis? axis = null, float showFromOffset = 0.0f, float hideToOffset = 0.0f, Vector3? centerPoint = null, float showFromScale = 1.0f, float hideToScale = 1.0f, float showDuration = 800.0f, float hideDuration = 800.0f, int showDelay = 0, int hideDelay = 0, bool animateOpacity = true) { var elementVisual = element.Visual(); var compositor = elementVisual.Compositor; ElementCompositionPreview.SetIsTranslationEnabled(element, true); ScalarKeyFrameAnimation hideOpacityAnimation = null; ScalarKeyFrameAnimation showOpacityAnimation = null; ScalarKeyFrameAnimation hideOffsetAnimation = null; ScalarKeyFrameAnimation showOffsetAnimation = null; Vector2KeyFrameAnimation hideScaleAnimation = null; Vector2KeyFrameAnimation showeScaleAnimation = null; if (animateOpacity) { hideOpacityAnimation = compositor.CreateScalarKeyFrameAnimation(); hideOpacityAnimation.InsertKeyFrame(1.0f, 0.0f); hideOpacityAnimation.Duration = TimeSpan.FromMilliseconds(hideDuration); hideOpacityAnimation.DelayTime = TimeSpan.FromMilliseconds(hideDelay); hideOpacityAnimation.Target = "Opacity"; } if (!hideToOffset.Equals(0.0f)) { hideOffsetAnimation = compositor.CreateScalarKeyFrameAnimation(); hideOffsetAnimation.InsertKeyFrame(1.0f, hideToOffset); hideOffsetAnimation.Duration = TimeSpan.FromMilliseconds(hideDuration); hideOffsetAnimation.DelayTime = TimeSpan.FromMilliseconds(hideDelay); hideOffsetAnimation.Target = $"Translation.{axis}"; } if (centerPoint.HasValue) { elementVisual.CenterPoint = centerPoint.Value; } if (!hideToScale.Equals(1.0f)) { hideScaleAnimation = compositor.CreateVector2KeyFrameAnimation(); hideScaleAnimation.InsertKeyFrame(1.0f, new Vector2(hideToScale)); hideScaleAnimation.Duration = TimeSpan.FromMilliseconds(hideDuration); hideScaleAnimation.DelayTime = TimeSpan.FromMilliseconds(hideDelay); hideScaleAnimation.Target = "Scale.XY"; } var hideAnimationGroup = compositor.CreateAnimationGroup(); if (hideOpacityAnimation != null) { hideAnimationGroup.Add(hideOpacityAnimation); } if (hideOffsetAnimation != null) { hideAnimationGroup.Add(hideOffsetAnimation); } if (hideScaleAnimation != null) { hideAnimationGroup.Add(hideScaleAnimation); } ElementCompositionPreview.SetImplicitHideAnimation(element, hideAnimationGroup); if (animateOpacity) { showOpacityAnimation = compositor.CreateScalarKeyFrameAnimation(); showOpacityAnimation.InsertKeyFrame(1.0f, 1.0f); showOpacityAnimation.Duration = TimeSpan.FromMilliseconds(showDuration); showOpacityAnimation.DelayTime = TimeSpan.FromMilliseconds(showDelay); showOpacityAnimation.Target = "Opacity"; } if (!showFromOffset.Equals(0.0f)) { showOffsetAnimation = compositor.CreateScalarKeyFrameAnimation(); showOffsetAnimation.InsertKeyFrame(0.0f, showFromOffset); showOffsetAnimation.InsertKeyFrame(1.0f, 0.0f); showOffsetAnimation.Duration = TimeSpan.FromMilliseconds(showDuration); showOffsetAnimation.DelayTime = TimeSpan.FromMilliseconds(showDelay); showOffsetAnimation.Target = $"Translation.{axis}"; } if (!showFromScale.Equals(1.0f)) { showeScaleAnimation = compositor.CreateVector2KeyFrameAnimation(); showeScaleAnimation.InsertKeyFrame(0.0f, new Vector2(showFromScale)); showeScaleAnimation.InsertKeyFrame(1.0f, Vector2.One); showeScaleAnimation.Duration = TimeSpan.FromMilliseconds(showDuration); showeScaleAnimation.DelayTime = TimeSpan.FromMilliseconds(showDelay); showeScaleAnimation.Target = "Scale.XY"; } var showAnimationGroup = compositor.CreateAnimationGroup(); if (showOpacityAnimation != null) { showAnimationGroup.Add(showOpacityAnimation); } if (showOffsetAnimation != null) { showAnimationGroup.Add(showOffsetAnimation); } if (showeScaleAnimation != null) { showAnimationGroup.Add(showeScaleAnimation); } ElementCompositionPreview.SetImplicitShowAnimation(element, showAnimationGroup); } public static void EnableImplicitAnimation(this UIElement element, VisualPropertyType typeToAnimate, double duration = 800, double delay = 0, CompositionEasingFunction easing = null) { var visual = element.Visual(); var compositor = visual.Compositor; var animationCollection = compositor.CreateImplicitAnimationCollection(); foreach (var type in UtilExtensions.GetValues()) { if (!typeToAnimate.HasFlag(type)) continue; var animation = CreateAnimationByType(compositor, type, duration, delay, easing); if (animation != null) { animationCollection[type.ToString()] = animation; } } visual.ImplicitAnimations = animationCollection; } public static void EnableImplicitAnimation(this Visual visual, VisualPropertyType typeToAnimate, double duration = 800, double delay = 0, CompositionEasingFunction easing = null) { var compositor = visual.Compositor; var animationCollection = compositor.CreateImplicitAnimationCollection(); foreach (var type in UtilExtensions.GetValues()) { if (!typeToAnimate.HasFlag(type)) continue; var animation = CreateAnimationByType(compositor, type, duration, delay, easing); if (animation != null) { animationCollection[type.ToString()] = animation; } } visual.ImplicitAnimations = animationCollection; } private static KeyFrameAnimation CreateAnimationByType(Compositor compositor, VisualPropertyType type, double duration = 800, double delay = 0, CompositionEasingFunction easing = null) { KeyFrameAnimation animation; switch (type) { case VisualPropertyType.Offset: case VisualPropertyType.Scale: animation = compositor.CreateVector3KeyFrameAnimation(); break; case VisualPropertyType.Size: animation = compositor.CreateVector2KeyFrameAnimation(); break; case VisualPropertyType.Opacity: case VisualPropertyType.RotationAngleInDegrees: animation = compositor.CreateScalarKeyFrameAnimation(); break; default: return null; } animation.InsertExpressionKeyFrame(1.0f, "this.FinalValue", easing); animation.Duration = TimeSpan.FromMilliseconds(duration); animation.DelayTime = TimeSpan.FromMilliseconds(delay); animation.Target = type.ToString(); return animation; } } }