/// <summary>
        /// An animation which will apply the derived effect.
        /// </summary>
        /// <param name="animationSet">The animation set.</param>
        /// <param name="value">The value.</param>
        /// <param name="duration">The duration in milliseconds.</param>
        /// <param name="delay">The delay in milliseconds.</param>
        /// <param name="easingType">The easing function to use</param>
        /// <param name="easingMode">The easing mode to use</param>
        /// <returns>An animation set with the effect added to it.</returns>
        public AnimationSet EffectAnimation(
            AnimationSet animationSet,
            double value          = 0d,
            double duration       = 500d,
            double delay          = 0d,
            EasingType easingType = EasingType.Default,
            EasingMode easingMode = EasingMode.EaseOut)
        {
            if (animationSet == null)
            {
                return(null);
            }

            if (!IsSupported)
            {
                return(null);
            }

            var visual           = animationSet.Visual;
            var associatedObject = animationSet.Element as FrameworkElement;

            if (associatedObject == null)
            {
                return(animationSet);
            }

            Compositor = visual?.Compositor;

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

            // check to see if the visual already has an effect applied.
            var spriteVisual = ElementCompositionPreview.GetElementChildVisual(associatedObject) as SpriteVisual;

            EffectBrush = spriteVisual?.Brush as CompositionEffectBrush;

            if (EffectBrush == null || EffectBrush?.Comment != EffectName)
            {
                _effectProperties   = ApplyEffect();
                EffectBrush.Comment = EffectName;

                var sprite = Compositor.CreateSpriteVisual();
                sprite.Brush = EffectBrush;
                ElementCompositionPreview.SetElementChildVisual(associatedObject, sprite);

                sprite.Size = new Vector2((float)associatedObject.ActualWidth, (float)associatedObject.ActualHeight);

                associatedObject.SizeChanged +=
                    (s, e) =>
                {
                    sprite.Size = new Vector2(
                        (float)associatedObject.ActualWidth,
                        (float)associatedObject.ActualHeight);
                };
            }

            if (duration <= 0)
            {
                foreach (var effectProperty in _effectProperties)
                {
                    animationSet.AddEffectDirectPropertyChange(EffectBrush, (float)value, effectProperty);
                }
            }
            else
            {
                foreach (var effectProperty in _effectProperties)
                {
                    var animation = Compositor.CreateScalarKeyFrameAnimation();
                    animation.InsertKeyFrame(1f, (float)value, AnimationExtensions.GetCompositionEasingFunction(easingType, Compositor, easingMode));

                    animation.Duration  = TimeSpan.FromMilliseconds(duration);
                    animation.DelayTime = TimeSpan.FromMilliseconds(delay);

                    animationSet.AddCompositionEffectAnimation(EffectBrush, animation, effectProperty);
                }
            }

            // Saturation starts from 1 to 0, instead of 0 to 1 so this makes sure the
            // the brush isn't removed from the UI element incorrectly. Completing on
            // Saturation as it's reusing the same sprite visual. Removing the Sprite removes the effect.
            if (EffectName != "Saturation" && value == 0)
            {
                animationSet.Completed += AnimationSet_Completed;
            }

            return(animationSet);
        }
Esempio n. 2
0
        public static AnimationSet Blur(
            this AnimationSet animationSet,
            double value    = 0d,
            double duration = 500d,
            double delay    = 0d)
        {
            if (animationSet == null)
            {
                return(null);
            }

            if (!IsBlurSupported)
            {
                //  The operating system doesn't support blur.
                //  Fail gracefully by not applying blur.
                //  See 'IsBlurSupported' property
                return(null);
            }

            var visual           = animationSet.Visual;
            var associatedObject = animationSet.Element as FrameworkElement;

            if (associatedObject == null)
            {
                return(animationSet);
            }

            var          compositor = visual?.Compositor;
            const string blurName   = "Blur";

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

            //  check to see if the visual already has a blur applied.
            var spriteVisual = ElementCompositionPreview.GetElementChildVisual(associatedObject) as SpriteVisual;
            var blurBrush    = spriteVisual?.Brush as CompositionEffectBrush;

            if (blurBrush == null || blurBrush.Comment != blurName)
            {
                var blurEffect = new GaussianBlurEffect
                {
                    Name         = blurName,
                    BlurAmount   = 0f,
                    Optimization = EffectOptimization.Balanced,
                    BorderMode   = EffectBorderMode.Hard,
                    Source       = new CompositionEffectSourceParameter("source")
                };

                //  Create a brush to which I want to apply. I also have noted that BlurAmount should be left out of the compiled shader.
                blurBrush         = compositor.CreateEffectFactory(blurEffect, new[] { $"{blurName}.BlurAmount" }).CreateBrush();
                blurBrush.Comment = blurName;

                //  Set the source of the blur as a backdrop brush
                blurBrush.SetSourceParameter("source", compositor.CreateBackdropBrush());

                var blurSprite = compositor.CreateSpriteVisual();
                blurSprite.Brush = blurBrush;
                ElementCompositionPreview.SetElementChildVisual(associatedObject, blurSprite);

                blurSprite.Size = new Vector2((float)associatedObject.ActualWidth, (float)associatedObject.ActualHeight);

                associatedObject.SizeChanged += (s, e) =>
                {
                    blurSprite.Size = new Vector2((float)associatedObject.ActualWidth, (float)associatedObject.ActualHeight);
                };
            }

            if (duration <= 0)
            {
                animationSet.AddEffectDirectPropertyChange(blurBrush, (float)value, $"{blurName}.BlurAmount");
            }
            else
            {
                //  Create an animation to change the blur amount over time
                var blurAnimation = compositor.CreateScalarKeyFrameAnimation();
                blurAnimation.InsertKeyFrame(1f, (float)value);
                blurAnimation.Duration  = TimeSpan.FromMilliseconds(duration);
                blurAnimation.DelayTime = TimeSpan.FromMilliseconds(delay);

                animationSet.AddCompositionEffectAnimation(blurBrush, blurAnimation, $"{blurName}.BlurAmount");
            }

            if (value == 0)
            {
                animationSet.Completed += AnimationSet_Completed;
            }

            return(animationSet);
        }