/// <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); }
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); }