Ejemplo n.º 1
0
        private void ConfigureAnimations(Visual photoVisual, Visual infoVisual, SpriteVisual shadowVisual)
        {
            // Create a drop shadow to be animated by the manipulation
            var shadow = _compositor.CreateDropShadow();

            shadowVisual.Shadow = shadow;
            _props.InsertScalar("progress", 0);

            // Create an animation that tracks the progress of the manipulation and stores it in a the PropertySet _props
            var trackerNode = _tracker.GetReference();

            _props.StartAnimation("progress", trackerNode.Position.Y / trackerNode.MaxPosition.Y);

            // Create an animation that scales up the infoVisual based on the manipulation progress
            var propSetProgress = _props.GetReference().GetScalarProperty("progress");

            infoVisual.StartAnimation("Scale", EF.Vector3(1, 1, 1) * EF.Lerp(1, 1.2f, propSetProgress));

            // Create an animation that changes the offset of the photoVisual and shadowVisual based on the manipulation progress
            var photoOffsetExp = -120f * _props.GetReference().GetScalarProperty("Progress");

            photoVisual.StartAnimation("offset.y", photoOffsetExp);
            shadowVisual.StartAnimation("offset.y", photoOffsetExp);

            // Create an animation that fades in the info visual based on the manipulation progress
            infoVisual.StartAnimation("opacity", EF.Lerp(0, 1, _props.GetReference().GetScalarProperty("Progress")));
            shadow.StartAnimation("blurradius", EF.Lerp(1, 50, _props.GetReference().GetScalarProperty("Progress")));
        }
Ejemplo n.º 2
0
        private Visual GetVideoRecording(Compositor compositor, float width, float height, Color color)
        {
            // Begin ellipse
            var ellipse = compositor.CreateEllipseGeometry();

            var ellipseSprite = compositor.CreateSpriteShape(ellipse);
            var ellipseBrush  = ellipseSprite.FillBrush = compositor.CreateColorBrush(color);

            ellipseSprite.Offset = new Vector2(width / 2, height / 2);

            // Begin shape
            var shape = compositor.CreateShapeVisual();

            shape.Shapes.Add(ellipseSprite);
            shape.Size  = new Vector2(width, height);
            shape.Scale = new Vector3(2, 2, 0);

            // Begin animation
            var props = compositor.CreatePropertySet();

            props.InsertScalar("animationValue", 0.0f);

            var reference      = props.GetReference();
            var animationValue = reference.GetScalarProperty("animationValue");

            var easing             = compositor.CreateCubicBezierEasingFunction(new Vector2(0.42f, 0), new Vector2(0.58f, 1));
            var animationValueImpl = compositor.CreateScalarKeyFrameAnimation();

            animationValueImpl.InsertKeyFrame(0, 0, easing);
            animationValueImpl.InsertKeyFrame(1, 1, easing);
            animationValueImpl.Duration          = TimeSpan.FromMilliseconds(900);
            animationValueImpl.IterationBehavior = AnimationIterationBehavior.Forever;

            props.StartAnimation("animationValue", animationValueImpl);

            ScalarNode animValue = EF.Conditional(animationValue < 0.5f, animationValue / 0.5f, (1 - animationValue) / 0.5f);

            ScalarNode alpha  = 1.0f - animValue * 0.6f;
            ScalarNode radius = 3.5f - animValue * 0.66f;

            ExpressionNode colorEllipse  = EF.ColorRgb(alpha * 255, color.R, color.G, color.B);
            ExpressionNode radiusEllipse = EF.Vector2(radius, radius);

            ellipseBrush.StartAnimation("Color", colorEllipse);
            ellipse.StartAnimation("Radius", radiusEllipse);

            return(shape);
        }
Ejemplo n.º 3
0
        private void OnTilePointerPressed(object sender, PointerRoutedEventArgs e)
        {
            var tileGrid     = (Grid)sender;
            var colorElement = (Rectangle)tileGrid.FindName("ColorElement");

            // Set the CenterPoint of the backing Visual, so the rotation axis will defined from the middle.
            colorElement.Visual().CenterPoint = new Vector3(tileGrid.RenderSize.ToVector2() / 2, 0.0f);

            // Calculate distance from corner of quadrant to Center
            _center = colorElement.Visual().CenterPoint;
            var xSquared = Math.Pow(tileGrid.ActualWidth / 2, 2);
            var ySquared = Math.Pow(tileGrid.ActualHeight / 2, 2);

            _distanceToCenter = (float)Math.Sqrt(xSquared + ySquared);

            // || DEFINE THE EXPRESSION FOR THE ROTATION ANGLE ||
            // We calculate the Rotation Angle such that it increases from 0 to 3 as the cursor position moves away from the center.
            // Combined with animating the Rotation Axis, the image is "push down" on the point at which the cursor is located.
            var pointerPositionProperties = ElementCompositionPreview.GetPointerPositionPropertySet(tileGrid);
            var pointerPosition           = pointerPositionProperties.GetSpecializedReference <PointerPositionPropertySetReferenceNode>().Position;
            var angleExpressionNode       = 3 * (EF.Clamp(EF.Distance(_center, pointerPosition), 0, _distanceToCenter) % _distanceToCenter / _distanceToCenter);

            var rotationAngleAnimation = _compositor.CreateScalarKeyFrameAnimation();

            rotationAngleAnimation.Duration = TimeSpan.FromMilliseconds(600);
            rotationAngleAnimation.InsertExpressionKeyFrame(0.4f, angleExpressionNode);
            rotationAngleAnimation.InsertKeyFrame(1.0f, 0.0f);

            colorElement.Visual().StartAnimation("RotationAngleInDegrees", rotationAngleAnimation);

            // || DEFINE THE EXPRESSION FOR THE ROTATION AXIS ||
            // The RotationAxis will be defined as the axis perpendicular to vector position of the hover pointer (vector from center to hover position).
            // The axis is a vector calculated by first converting the pointer position into the coordinate space where the center point (0, 0) is in the middle.
            // The perpendicular axis is then calculated by transposing the cartesian x, y components and negating one (e.g. Vector3(-y,x,0) )
            var axisAngleExpressionNode = EF.Floor((pointerPosition.X - _center.X) * EF.Conditional(pointerPosition.X == _center.X, 0, 1));

            var rotationAxisAnimation = _compositor.CreateScalarKeyFrameAnimation();

            rotationAxisAnimation.Duration = TimeSpan.FromMilliseconds(600);
            rotationAxisAnimation.InsertExpressionKeyFrame(0.4f, axisAngleExpressionNode);
            rotationAxisAnimation.InsertKeyFrame(1.0f, 0.0f);

            colorElement.Visual().StartAnimation("RotationAxis.Y", rotationAxisAnimation);
        }
Ejemplo n.º 4
0
        private void TiltUIElement()
        {
            // Grab the backing Visual for the UIElement image
            _tiltVisual = ElementCompositionPreview.GetElementVisual(tiltImage);

            // Set the CenterPoint of the backing Visual, so the rotation axis will defined from the middle
            _tiltVisual.CenterPoint = new Vector3((float)tiltImage.Width / 2, (float)tiltImage.Height / 2, 0f);

            // Grab the PropertySet containing the hover pointer data that will be used to drive the rotations
            // Note: We have a second UIElement we will grab the pointer data against and the other we will animate
            _hoverPositionPropertySet = ElementCompositionPreview.GetPointerPositionPropertySet(HitTestRect);

            // Calculate distance from corner of quadrant to Center
            var center           = new Vector3((float)tiltImage.Width / 2, (float)tiltImage.Height / 2, 0);
            var xSquared         = Math.Pow(tiltImage.Width / 2, 2);
            var ySquared         = Math.Pow(tiltImage.Height / 2, 2);
            var distanceToCenter = (float)Math.Sqrt(xSquared + ySquared);

            // || DEFINE THE EXPRESSION FOR THE ROTATION ANGLE ||
            // We calculate the Rotation Angle such that it increases from 0 to 35 as the cursor position moves away from the center.
            // Combined with animating the Rotation Axis, the image is "push down" on the point at which the cursor is located.
            // Note: We special case when the hover position is (0,0,0) as this is the starting hover position and and we want the image to be flat (rotationAngle = 0) at startup.
            var hoverPosition       = _hoverPositionPropertySet.GetSpecializedReference <PointerPositionPropertySetReferenceNode>().Position;
            var angleExpressionNode =
                EF.Conditional(
                    hoverPosition == new Vector3(0, 0, 0),
                    ExpressionValues.CurrentValue.CreateScalarCurrentValue(),
                    35 * ((EF.Clamp(EF.Distance(center, hoverPosition), 0, distanceToCenter) % distanceToCenter) / distanceToCenter));

            _tiltVisual.StartAnimation("RotationAngleInDegrees", angleExpressionNode);

            // || DEFINE THE EXPRESSION FOR THE ROTATION AXIS ||
            // The RotationAxis will be defined as the axis perpendicular to vector position of the hover pointer (vector from center to hover position).
            // The axis is a vector calculated by first converting the pointer position into the coordinate space where the center point (0, 0) is in the middle.
            // The perpendicular axis is then calculated by transposing the cartesian x, y components and negating one (e.g. Vector3(-y,x,0) )
            var axisAngleExpressionNode = EF.Vector3(
                -(hoverPosition.Y - center.Y) * EF.Conditional(hoverPosition.Y == center.Y, 0, 1),
                (hoverPosition.X - center.X) * EF.Conditional(hoverPosition.X == center.X, 0, 1),
                0);

            _tiltVisual.StartAnimation("RotationAxis", axisAngleExpressionNode);
        }
        private void SetupExpressionAnimationsForCard()
        {
            _cardVisual = VisualExtensions.GetVisual(Card);
            _cardVisual.RelativeSizeAdjustment = Vector2.One;
            _cardVisual.CenterPoint            = new Vector3(Card.RenderSize.ToVector2() / 2, 0.0f);

            var initialPositionY = (float)ActualHeight;

            _cardVisual.Offset = new Vector3(0.0f, initialPositionY, 0.0f);

            _progress.InsertScalar("Progress", 0);
            var progressExpressionNode = _progress.GetReference().GetScalarProperty("Progress");

            // Scale the card visual based on the progress.
            _cardVisual.StartAnimation("Scale", EF.Vector3(1.0f, 1.0f, 1.0f) * EF.Lerp(0.6f, 1.0f, progressExpressionNode));
            // Fade in the card visual based on the progress.
            _cardVisual.StartAnimation("Opacity", EF.Lerp(0.0f, 1.0f, progressExpressionNode));
            // Move the card visual based on the progress.
            var offset = initialPositionY * (1.0f - progressExpressionNode);

            _cardVisual.StartAnimation("Offset.Y", offset);
        }
Ejemplo n.º 6
0
        private Visual GetPlaying(Compositor compositor, float width, float height, Color color)
        {
            float distance    = 4.0f;
            float x           = (width - distance * 2) / 2.0f;
            float y           = height / 2.0f + 1;
            float radius      = 1.0f;
            float mouthRadius = 3.5f;

            // Begin dot1
            var dot1 = compositor.CreateEllipseGeometry();

            dot1.Radius = new Vector2(radius, radius);

            var spriteDot1 = compositor.CreateSpriteShape(dot1);

            spriteDot1.FillBrush = compositor.CreateColorBrush(color);

            // Begin dot2
            var dot2 = compositor.CreateEllipseGeometry();

            dot2.Radius = new Vector2(radius, radius);

            var spriteDot2 = compositor.CreateSpriteShape(dot2);

            spriteDot2.FillBrush = compositor.CreateColorBrush(color);

            // Begin dot2
            var dot3 = compositor.CreateEllipseGeometry();

            dot3.Radius = new Vector2(radius, radius);

            var spriteDot3 = compositor.CreateSpriteShape(dot3);
            var brushDot3  = spriteDot3.FillBrush = compositor.CreateColorBrush(Color.FromArgb(0, 0, 0, 0));

            // Begin mouth
            var mouth = compositor.CreateEllipseGeometry();

            mouth.Radius = new Vector2(mouthRadius / 2, mouthRadius / 2);

            var spriteMouth = compositor.CreateSpriteShape(mouth);

            spriteMouth.StrokeThickness        = mouthRadius;
            spriteMouth.StrokeBrush            = compositor.CreateColorBrush(color);
            spriteMouth.RotationAngleInDegrees = 90;
            spriteMouth.Offset = new Vector2(mouthRadius, y - 1);

            // Begin shape
            var shape = compositor.CreateShapeVisual();

            shape.Shapes.Add(spriteDot1);
            shape.Shapes.Add(spriteDot2);
            shape.Shapes.Add(spriteDot3);
            shape.Shapes.Add(spriteMouth);
            shape.Size  = new Vector2(width, height);
            shape.Scale = new Vector3(2, 2, 0);

            // Begin animation
            var props = compositor.CreatePropertySet();

            props.InsertScalar("animationValue", 0.0f);
            props.InsertScalar("dotsProgress", 0.0f);
            props.InsertScalar("dotsX", 0.0f);
            props.InsertScalar("bite", 0.0f);

            var reference      = props.GetReference();
            var animationValue = reference.GetScalarProperty("animationValue");
            var dotsProgress   = reference.GetScalarProperty("dotsProgress");
            var dotsX          = reference.GetScalarProperty("dotsX");
            var bite           = reference.GetScalarProperty("bite");

            var easing             = compositor.CreateLinearEasingFunction();
            var animationValueImpl = compositor.CreateScalarKeyFrameAnimation();

            animationValueImpl.InsertKeyFrame(0, 0, easing);
            animationValueImpl.InsertKeyFrame(1, 1, easing);
            animationValueImpl.Duration          = TimeSpan.FromMilliseconds(700);
            animationValueImpl.IterationBehavior = AnimationIterationBehavior.Forever;

            var biteImpl = compositor.CreateScalarKeyFrameAnimation();

            biteImpl.InsertKeyFrame(0.00f, 0, easing);
            biteImpl.InsertKeyFrame(0.25f, 1, easing);
            biteImpl.InsertKeyFrame(0.50f, 0, easing);
            biteImpl.InsertKeyFrame(0.75f, 1, easing);
            biteImpl.InsertKeyFrame(1.00f, 0, easing);
            biteImpl.Duration          = TimeSpan.FromMilliseconds(700);
            biteImpl.IterationBehavior = AnimationIterationBehavior.Forever;

            props.StartAnimation("animationValue", animationValueImpl);
            props.StartAnimation("bite", biteImpl);

            ExpressionNode animationDotsProgress = (EF.Ceil(animationValue * 100) % 50) / 50;
            ExpressionNode animationDotsX        = 1.5f + x - distance * dotsProgress;

            props.StartAnimation("dotsProgress", animationDotsProgress);
            props.StartAnimation("dotsX", animationDotsX);

            ExpressionNode moveDot1  = EF.Vector2(dotsX - radius, y - radius);
            ExpressionNode moveDot2  = EF.Vector2(dotsX - radius + distance, y - radius);
            ExpressionNode moveDot3  = EF.Vector2(dotsX - radius + distance * 2, y - radius);
            ExpressionNode colorDot3 = EF.ColorRgb(dotsProgress * 255, color.R, color.G, color.B);

            spriteDot1.StartAnimation("Offset", moveDot1);
            spriteDot2.StartAnimation("Offset", moveDot2);
            spriteDot3.StartAnimation("Offset", moveDot3);
            brushDot3.StartAnimation("Color", colorDot3);

            ExpressionNode start = bite * 0.125f;
            ExpressionNode end   = 1 - bite * 0.125f;

            mouth.StartAnimation("TrimStart", start);
            mouth.StartAnimation("TrimEnd", end);

            return(shape);
        }
Ejemplo n.º 7
0
        private Visual GetUploading(Compositor compositor, float width, float height, Color color)
        {
            float progressWidth  = 26.0f / 2.0f;
            float progressHeight = 8.0f / 2.0f;

            float leftPadding = 0.0f;
            float topPadding  = height / 2.0f - progressHeight / 2.0f;

            float round = 1.25f;

            // Begin background
            var background = compositor.CreateRoundedRectangleGeometry();

            background.Offset       = new Vector2(leftPadding, topPadding);
            background.Size         = new Vector2(progressWidth, progressHeight);
            background.CornerRadius = new Vector2(round);

            var spriteBackground = compositor.CreateSpriteShape(background);

            spriteBackground.FillBrush = compositor.CreateColorBrush(color);

            // Begin overlay
            var overlay = compositor.CreateRoundedRectangleGeometry();

            overlay.Offset       = new Vector2(leftPadding, topPadding);
            overlay.Size         = new Vector2(progressWidth, progressHeight);
            overlay.CornerRadius = new Vector2(round);

            var spriteOverlay = compositor.CreateSpriteShape(overlay);

            spriteOverlay.FillBrush = compositor.CreateColorBrush(Color.FromArgb(75, color.R, color.G, color.B));

            // Begin bar
            var bar = compositor.CreateRoundedRectangleGeometry();

            bar.Offset       = new Vector2(leftPadding - progressWidth + 0, topPadding);
            bar.Size         = new Vector2(progressWidth, progressHeight);
            bar.CornerRadius = new Vector2(round);

            var spriteBar = compositor.CreateSpriteShape(bar);

            spriteBar.FillBrush = compositor.CreateColorBrush(color);

            var shape = compositor.CreateShapeVisual();

            //shape.Shapes.Add(spriteBackground);
            shape.Shapes.Add(spriteOverlay);
            shape.Shapes.Add(spriteBar);
            shape.Size  = new Vector2(width, height);
            shape.Scale = new Vector3(2, 2, 0);
            shape.Clip  = compositor.CreateGeometricClip(background);

            // Begin animation
            var props = compositor.CreatePropertySet();

            props.InsertScalar("animationValue", 0.0f);

            var reference      = props.GetReference();
            var animationValue = reference.GetScalarProperty("animationValue");

            var easing             = compositor.CreateCubicBezierEasingFunction(new Vector2(0.42f, 0), new Vector2(0.58f, 1));
            var animationValueImpl = compositor.CreateScalarKeyFrameAnimation();

            animationValueImpl.InsertKeyFrame(1, 0, easing);
            animationValueImpl.InsertKeyFrame(1, 1, easing);
            animationValueImpl.Duration          = TimeSpan.FromMilliseconds(1750);
            animationValueImpl.IterationBehavior = AnimationIterationBehavior.Forever;

            props.StartAnimation("animationValue", animationValueImpl);

            ScalarNode     progress = (animationValue * (progressWidth * 2.0f));
            ExpressionNode moveBar  = EF.Vector2(leftPadding - progressWidth + progress, topPadding);

            bar.StartAnimation("Offset", moveBar);

            return(shape);
        }
Ejemplo n.º 8
0
        private Visual GetVoiceRecording(Compositor compositor, float width, float height, Color color)
        {
            float delta = 3.0f;
            float x     = 3.0f;
            float y     = height / 2.0f;

            // Begin dot1
            var dot1 = compositor.CreateEllipseGeometry();

            dot1.TrimStart = 0.5f - 0.05f;
            dot1.TrimEnd   = 0.5f + 0.05f;

            var spriteDot1 = compositor.CreateSpriteShape(dot1);
            var brushDot1  = spriteDot1.StrokeBrush = compositor.CreateColorBrush(color);

            spriteDot1.StrokeThickness        = 1.5f;
            spriteDot1.Offset                 = new Vector2(x, y);
            spriteDot1.StrokeStartCap         = CompositionStrokeCap.Round;
            spriteDot1.StrokeEndCap           = CompositionStrokeCap.Round;
            spriteDot1.RotationAngleInDegrees = -90;

            // Begin dot2
            var dot2 = compositor.CreateEllipseGeometry();

            dot2.TrimStart = 0.5f - 0.05f;
            dot2.TrimEnd   = 0.5f + 0.05f;

            var spriteDot2 = compositor.CreateSpriteShape(dot2);
            var brushDot2  = spriteDot2.StrokeBrush = compositor.CreateColorBrush(color);

            spriteDot2.StrokeThickness        = 1.5f;
            spriteDot2.Offset                 = new Vector2(x, y);
            spriteDot2.StrokeStartCap         = CompositionStrokeCap.Round;
            spriteDot2.StrokeEndCap           = CompositionStrokeCap.Round;
            spriteDot2.RotationAngleInDegrees = -90;

            // Begin dot2
            var dot3 = compositor.CreateEllipseGeometry();

            dot3.TrimStart = 0.5f - 0.05f;
            dot3.TrimEnd   = 0.5f + 0.05f;

            var spriteDot3 = compositor.CreateSpriteShape(dot3);
            var brushDot3  = spriteDot3.StrokeBrush = compositor.CreateColorBrush(color);

            spriteDot3.StrokeThickness        = 1.5f;
            spriteDot3.Offset                 = new Vector2(x, y);
            spriteDot3.StrokeStartCap         = CompositionStrokeCap.Round;
            spriteDot3.StrokeEndCap           = CompositionStrokeCap.Round;
            spriteDot3.RotationAngleInDegrees = -90;

            // Begin shape
            var shape = compositor.CreateShapeVisual();

            shape.Shapes.Add(spriteDot1);
            shape.Shapes.Add(spriteDot2);
            shape.Shapes.Add(spriteDot3);
            shape.Size  = new Vector2(width, height);
            shape.Scale = new Vector3(2, 2, 0);

            // Begin animation
            var props = compositor.CreatePropertySet();

            props.InsertScalar("animationValue", 0.0f);

            var reference      = props.GetReference();
            var animationValue = reference.GetScalarProperty("animationValue");

            var easing             = compositor.CreateLinearEasingFunction();
            var animationValueImpl = compositor.CreateScalarKeyFrameAnimation();

            animationValueImpl.InsertKeyFrame(0, 0, easing);
            animationValueImpl.InsertKeyFrame(1, 1, easing);
            animationValueImpl.Duration          = TimeSpan.FromMilliseconds(700);
            animationValueImpl.IterationBehavior = AnimationIterationBehavior.Forever;

            props.StartAnimation("animationValue", animationValueImpl);

            ScalarNode     radiusz    = animationValue * delta;
            ExpressionNode radiusDot1 = EF.Vector2(radiusz, radiusz);
            ExpressionNode radiusDot2 = EF.Vector2(radiusz + delta, radiusz + delta);
            ExpressionNode radiusDot3 = EF.Vector2(radiusz + delta * 2, radiusz + delta * 2);

            dot1.StartAnimation("Radius", radiusDot1);
            dot2.StartAnimation("Radius", radiusDot2);
            dot3.StartAnimation("Radius", radiusDot3);

            ScalarNode alpha;

            alpha = 1.0f - EF.Pow(EF.Cos(radiusz / (3.0f * delta) * PI), 10);
            ExpressionNode colorDot1 = EF.ColorRgb(alpha * 255, color.R, color.G, color.B);

            alpha = 1.0f - EF.Pow(EF.Cos((radiusz + delta) / (3.0f * delta) * PI), 10);
            ExpressionNode colorDot2 = EF.ColorRgb(alpha * 255, color.R, color.G, color.B);

            alpha = 1.0f - EF.Pow(EF.Cos((radiusz + delta * 2) / (3.0f * delta) * PI), 10);
            ExpressionNode colorDot3 = EF.ColorRgb(alpha * 255, color.R, color.G, color.B);

            brushDot1.StartAnimation("Color", colorDot1);
            brushDot2.StartAnimation("Color", colorDot2);
            brushDot3.StartAnimation("Color", colorDot3);

            return(shape);
        }
Ejemplo n.º 9
0
        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            // Retrieve the ScrollViewer that the GridView is using internally
            var scrollViewer = gridView.GetFirstDescendantOfType <ScrollViewer>();

            // Update the ZIndex of the header container so that the header is above the items when scrolling
            var headerPresenter = (UIElement)VisualTreeHelper.GetParent((UIElement)gridView.Header);
            var headerContainer = (UIElement)VisualTreeHelper.GetParent(headerPresenter);

            Canvas.SetZIndex((UIElement)headerContainer, 1);

            // Get the PropertySet that contains the scroll values from the ScrollViewer
            _scrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);
            _compositor          = _scrollerPropertySet.Compositor;

            // Create a PropertySet that has values to be referenced in the ExpressionAnimations below
            _props = _compositor.CreatePropertySet();
            _props.InsertScalar("progress", 0);
            _props.InsertScalar("clampSize", 150);
            _props.InsertScalar("scaleFactor", 0.7f);

            // Get references to our property sets for use with ExpressionNodes
            var scrollingProperties = _scrollerPropertySet.GetSpecializedReference <ManipulationPropertySetReferenceNode>();
            var props           = _props.GetReference();
            var progressNode    = props.GetScalarProperty("progress");
            var clampSizeNode   = props.GetScalarProperty("clampSize");
            var scaleFactorNode = props.GetScalarProperty("scaleFactor");

            // Create a blur effect to be animated based on scroll position
            var blurEffect = new GaussianBlurEffect()
            {
                Name         = "blur",
                BlurAmount   = 0.0f,
                BorderMode   = EffectBorderMode.Hard,
                Optimization = EffectOptimization.Balanced,
                Source       = new CompositionEffectSourceParameter("source")
            };

            var blurBrush = _compositor.CreateEffectFactory(
                blurEffect,
                new[] { "blur.BlurAmount" })
                            .CreateBrush();

            blurBrush.SetSourceParameter("source", _compositor.CreateBackdropBrush());

            // Create a Visual for applying the blur effect
            _blurredBackgroundImageVisual       = _compositor.CreateSpriteVisual();
            _blurredBackgroundImageVisual.Brush = blurBrush;
            _blurredBackgroundImageVisual.Size  = new Vector2((float)OverlayRectangle.ActualWidth, (float)OverlayRectangle.ActualHeight);

            // Insert the blur visual at the right point in the Visual Tree
            ElementCompositionPreview.SetElementChildVisual(OverlayRectangle, _blurredBackgroundImageVisual);

            // Create and start an ExpressionAnimation to track scroll progress over the desired distance
            ExpressionNode progressAnimation = EF.Clamp(-scrollingProperties.Translation.Y / clampSizeNode, 0, 1);

            _props.StartAnimation("progress", progressAnimation);

            // Create and start an ExpressionAnimation to animate blur radius between 0 and 15 based on progress
            ExpressionNode blurAnimation = EF.Lerp(0, 15, progressNode);

            _blurredBackgroundImageVisual.Brush.Properties.StartAnimation("blur.BlurAmount", blurAnimation);

            // Get the backing visual for the header so that its properties can be animated
            Visual headerVisual = ElementCompositionPreview.GetElementVisual(Header);

            // Create and start an ExpressionAnimation to clamp the header's offset to keep it onscreen
            ExpressionNode headerTranslationAnimation = EF.Conditional(progressNode < 1, 0, -scrollingProperties.Translation.Y - clampSizeNode);

            headerVisual.StartAnimation("Offset.Y", headerTranslationAnimation);

            // Create and start an ExpressionAnimation to scale the header during overpan
            ExpressionNode headerScaleAnimation = EF.Lerp(1, 1.25f, EF.Clamp(scrollingProperties.Translation.Y / 50, 0, 1));

            headerVisual.StartAnimation("Scale.X", headerScaleAnimation);
            headerVisual.StartAnimation("Scale.Y", headerScaleAnimation);

            //Set the header's CenterPoint to ensure the overpan scale looks as desired
            headerVisual.CenterPoint = new Vector3((float)(Header.ActualWidth / 2), (float)Header.ActualHeight, 0);

            // Get the backing visual for the photo in the header so that its properties can be animated
            Visual photoVisual = ElementCompositionPreview.GetElementVisual(BackgroundRectangle);

            // Create and start an ExpressionAnimation to opacity fade out the image behind the header
            ExpressionNode imageOpacityAnimation = 1 - progressNode;

            photoVisual.StartAnimation("opacity", imageOpacityAnimation);

            // Get the backing visual for the profile picture visual so that its properties can be animated
            Visual profileVisual = ElementCompositionPreview.GetElementVisual(ProfileImage);

            // Create and start an ExpressionAnimation to scale the profile image with scroll position
            ExpressionNode scaleAnimation = EF.Lerp(1, scaleFactorNode, progressNode);

            profileVisual.StartAnimation("Scale.X", scaleAnimation);
            profileVisual.StartAnimation("Scale.Y", scaleAnimation);

            // Get backing visuals for the text blocks so that their properties can be animated
            Visual blurbVisual    = ElementCompositionPreview.GetElementVisual(Blurb);
            Visual subtitleVisual = ElementCompositionPreview.GetElementVisual(SubtitleBlock);
            Visual moreVisual     = ElementCompositionPreview.GetElementVisual(MoreText);

            // Create an ExpressionAnimation that moves between 1 and 0 with scroll progress, to be used for text block opacity
            ExpressionNode textOpacityAnimation = EF.Clamp(1 - (progressNode * 2), 0, 1);

            // Start opacity and scale animations on the text block visuals
            blurbVisual.StartAnimation("Opacity", textOpacityAnimation);
            blurbVisual.StartAnimation("Scale.X", scaleAnimation);
            blurbVisual.StartAnimation("Scale.Y", scaleAnimation);

            subtitleVisual.StartAnimation("Opacity", textOpacityAnimation);
            subtitleVisual.StartAnimation("Scale.X", scaleAnimation);
            subtitleVisual.StartAnimation("Scale.Y", scaleAnimation);

            moreVisual.StartAnimation("Opacity", textOpacityAnimation);
            moreVisual.StartAnimation("Scale.X", scaleAnimation);
            moreVisual.StartAnimation("Scale.Y", scaleAnimation);

            // Get the backing visuals for the text and button containers so that their properites can be animated
            Visual textVisual   = ElementCompositionPreview.GetElementVisual(TextContainer);
            Visual buttonVisual = ElementCompositionPreview.GetElementVisual(ButtonPanel);

            // When the header stops scrolling it is 150 pixels offscreen.  We want the text header to end up with 50 pixels of its content
            // offscreen which means it needs to go from offset 0 to 100 as we traverse through the scrollable region
            ExpressionNode contentOffsetAnimation = progressNode * 100;

            textVisual.StartAnimation("Offset.Y", contentOffsetAnimation);

            ExpressionNode buttonOffsetAnimation = progressNode * -100;

            buttonVisual.StartAnimation("Offset.Y", buttonOffsetAnimation);
        }