private void SetupImageList() { // Note: Translation is an additive value to the Offset property when defining the final position of a backed visual of a UIElement // This Expression defines an equation that changes the Y Translation of an image based on the scale of its vertical neighbor image. // As the scale of an image grows, the images below it will dynamically move down. // The equation is built by summing up two different deltas caused by a scale animation: // 1) The delta caused by the image directly above the target scaling to a value > 1 (should have no effect if scale == 1) // 2) Any additional delta caused by if the image above has translated down because the image above it (or higher up) has scaled up // [Will either be a large scale from Click, or medium scale if on hover] // Note: 120 represents the height of the images + the gap between them var visualPlaceHolder = EV.Reference.CreateVisualReference("visual"); var factor = EV.Constant.CreateConstantScalar("factor"); _translationDeltaExp = ((visualPlaceHolder.Scale.Y - 1) * (float)image.Height) + EF.Conditional( ((visualPlaceHolder.Translation.Y / (120 * factor)) > 1), (EV.Constant.CreateConstantScalar("largeScaleDiff")), visualPlaceHolder.Translation.Y % (120 * factor) ); // Activate Translation property for Visuals backing a UIElement TranslationSetup(image); TranslationSetup(image2); TranslationSetup(image3); TranslationSetup(image4); // Setup the Expression on the Y Translation property for images 2 - 4. // Pass in the target image that the Expression gets applied to, the image above it for reference and images indexed position // Note: Since the first image does not have an image above it, do not need to apply the Expression to it StartAnimationHelper(image2, image, 1); StartAnimationHelper(image3, image2, 2); StartAnimationHelper(image4, image3, 3); }
private void ConfigureTemplateAnimations() { var propSetProgress = _props.GetReference().GetScalarProperty("progress"); var trackerNode = _tracker.GetReference(); foreach (var itemRendered in itemsRendered.Items) { var template = itemRendered.Item2; template.GetVisual().StopAnimation("offset.x"); template.GetVisual().StopAnimation("Scale"); template.GetVisual().StartAnimation("offset.x", _props.GetReference().GetScalarProperty("position") + itemRendered.Item1 * _itemWidth); float positionCenter = (itemRendered.Item1 * _itemWidth); float position = (itemRendered.Item1 * _itemWidth) - _itemWidth / 2; float positionEnd = (itemRendered.Item1 * _itemWidth) + _itemWidth / 2; template.GetVisual() .StartAnimation("Scale", EF.Vector3(1, 1, 1) * EF.Conditional(trackerNode.Position.X > position & trackerNode.Position.X < positionEnd , EF.Lerp(1.2f, 1, EF.Abs(positionCenter - trackerNode.Position.X) / (_itemWidth / 2)) , 1)); template.BackgroundPanel .StartAnimation("Scale", EF.Vector3(1, 1, 1) * EF.Conditional(trackerNode.Position.X > position & trackerNode.Position.X < positionEnd , EF.Lerp(1.1f, 1, EF.Abs(positionCenter - trackerNode.Position.X) / (_itemWidth / 2)) , 1)); template.Shadow .StartAnimation("opacity", EF.Conditional(trackerNode.Position.X > position & trackerNode.Position.X < positionEnd , EF.Lerp(1, 0, EF.Abs(positionCenter - trackerNode.Position.X) / (_itemWidth / 2)) , 0)); template.ContentPanel .StartAnimation("opacity", EF.Conditional(trackerNode.Position.X > position & trackerNode.Position.X < positionEnd , EF.Lerp(1, 0, EF.Abs(positionCenter - trackerNode.Position.X) / (_itemWidth / 2)) , 0)); template.OverlayPanel .StartAnimation("opacity", EF.Conditional(trackerNode.Position.X > position & trackerNode.Position.X < positionEnd , EF.Lerp(0, 0.6f, EF.Abs(positionCenter - trackerNode.Position.X) / (_itemWidth / 2)) , 0.6f)); } }
/// <summary> /// Create the _frontVisual and the animations that drive it. /// </summary> /// <param name="scrollProperties">A property set who has Translation.Y specified - typically the return from ElementCompositionPreview.GetScrollViewerManipulationPropertySet(...).</param> /// <param name="maskedBrush">This is the brush that will be set on _frontVisual</param> private void InitializeFrontVisual(CompositionPropertySet scrollProperties, CompositionEffectBrush maskedBrush) { // // Create the _frontVisual, set the brush on it, and attach it to the scrollViewer. Setting it as the // child visual on scrollviewer will put it in front of all the scrollViewer content. // _frontVisual = _compositor.CreateSpriteVisual(); _frontVisual.Brush = maskedBrush; ElementCompositionPreview.SetElementChildVisual(MainGrid, _frontVisual); // // "Terms" in the following expression: // // (CrossoverTranslation + scrollingProperties.Translation.Y)/CrossoverTranslation // // Since scrollingProperties.Translation.Y is negative. This creates a normalized value that goes from // 0 to 1 between no scrolling and the CrossoverTranslation. // var scrollPropSet = scrollProperties.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var crossoverTranslation = ExpressionValues.Constant.CreateConstantScalar("CrossoverTranslation"); _frontPropertiesScaleExpression = EF.Lerp( _finalScaleAmount, _initialScaleAmount, EF.Clamp((crossoverTranslation + scrollPropSet.Translation.Y) / crossoverTranslation, 0, 1)); // // The previous equation calculates a scalar which is later bound to ScalarScale in FrontVisual's Properties. // This equation uses that scalar to construct a new vector3 to set to animate the scale of the visual itself. // _frontVisual.Properties.InsertScalar("ScalarScale", 1); var frontScalarScale = _frontVisual.GetReference().GetScalarProperty("ScalarScale"); var vec3ScaleExpression = EF.Vector3(frontScalarScale, frontScalarScale, 1); _frontVisual.StartAnimation("Scale", vec3ScaleExpression); // // This equation controls whether or not the FrontVisual is visibile via opacity. It uses a simple ternary operator // to pick between 100% and 0% opacity based on the position being before the crossover point. // _frontVisibilityExpression = EF.Conditional(-scrollPropSet.Translation.Y <= crossoverTranslation, 1, 0); var baseOffset = ExpressionValues.Constant.CreateConstantScalar("BaseOffset"); _frontTranslationExpression = EF.Conditional(scrollPropSet.Translation.Y > 0, baseOffset, baseOffset - scrollPropSet.Translation.Y); }
/// <summary> /// Create the Visual that will host the profile background image and setup /// the animations that will drive it. /// </summary> /// /// <param name="scrollProperties">A property set who has Translation.Y specified - typically the return from ElementCompositionPreview.GetScrollViewerManipulationPropertySet(...).</param> private void InitializeBackgroundImageVisual(CompositionPropertySet scrollProperties) { // // Get the visual for the background image, and let it parallax up until the BackgroundPeekSize. // BackgroundPeekSize is later defined as the amount of the image to leave showing. // _backgroundVisual = ElementCompositionPreview.GetElementVisual(ParallaxingImage); // // If the scrolling is positive (i.e., bouncing), don't translate at all. Then check to see if // we have parallaxed as far as we should go. If we haven't, keep parallaxing otherwise use // the scrolling translation to keep the background stuck with the background peeking out. // var scrollPropSet = scrollProperties.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var baseOffsetParam = ExpressionValues.Constant.CreateConstantScalar("BaseOffset"); var backgroundPeekSize = ExpressionValues.Constant.CreateConstantScalar("BackgroundPeekSize"); _backgroundTranslateExpression = baseOffsetParam + EF.Conditional(scrollPropSet.Translation.Y > 0, 0, EF.Conditional(((1 - _parallaxRatio) * -scrollPropSet.Translation.Y) < backgroundPeekSize, (_parallaxRatio * -scrollPropSet.Translation.Y), -backgroundPeekSize - scrollPropSet.Translation.Y)); _backgroundScaleExpression = EF.Lerp(1, 1 + _backgroundScaleAmount, EF.Clamp(scrollPropSet.Translation.Y / 50, 0, 1)); _backgroundBlurExpression = EF.Clamp(-scrollPropSet.Translation.Y / (backgroundPeekSize * 0.5f), 0, 1); _backgroundInverseBlurExpression = 1 - EF.Clamp(-scrollPropSet.Translation.Y / (backgroundPeekSize * 0.5f), 0, 1); // // We want to keep the Name/Title text in the middle of the background image. To start with, // we add the centerpoint - since we move the anchor point to (.5,/5) which XAML layout doesn't // expect - and the background offset offset to keep the element positioned with the background. // we then lerp between its existing position and its final position based on parallaxed distance // traveled. // _profileContentVisual = ElementCompositionPreview.GetElementVisual(ProfileContent); var background = _backgroundVisual.GetReference(); _profileTranslationExpression = (-scrollPropSet.Translation.Y + background.Offset.Y + background.Size.Y / 2) / 2; _profileScaleExpression = EF.Lerp( 1, _contentShrinkRatio, EF.Clamp((background.Offset.Y - background.Size.Y / 2) / (background.Size.Y - backgroundPeekSize), 0, 1)); }
private void AlbumList_Loaded(object sender, RoutedEventArgs e) { var scrollviewer = AlbumList.GetScrollViewer(); var _scrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollviewer); var _compositor = _scrollerPropertySet.Compositor; // Get references to our property sets for use with ExpressionNodes var scrollingProperties = _scrollerPropertySet.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var headerHeight = (float)(HeaderGroup.ActualHeight - (0f + HeaderGroup.Margin.Bottom)); var toolbarHeight = (float)Toolbar.ActualHeight; var progressAnimation = EF.Conditional(-scrollingProperties.Translation.Y > headerHeight, EF.Conditional(-scrollingProperties.Translation.Y > headerHeight + toolbarHeight, 0, -scrollingProperties.Translation.Y - headerHeight - toolbarHeight), -toolbarHeight); // 0~1 progressAnimation = (progressAnimation + toolbarHeight) / toolbarHeight; var toolbarVisual = ElementCompositionPreview.GetElementVisual(Toolbar); toolbarVisual.StartAnimation("Offset.Y", progressAnimation * 16 - 16); var bgVisual = ElementCompositionPreview.GetElementVisual(TitleBG); bgVisual.StartAnimation("Opacity", progressAnimation); toolbarVisual.StartAnimation("Opacity", progressAnimation); var moving = 80f; var movingAnimation = EF.Conditional(-scrollingProperties.Translation.Y > moving, 0f, moving + scrollingProperties.Translation.Y); var scaleAnimation = EF.Clamp(-scrollingProperties.Translation.Y / moving, 0, 1); scaleAnimation = EF.Lerp(1, (float)(ToolbarTitle.ActualHeight / TitleText.ActualHeight), scaleAnimation); var titleVisual = ElementCompositionPreview.GetElementVisual(Title); titleVisual.StartAnimation("Offset.Y", movingAnimation); var titleTextVisual = ElementCompositionPreview.GetElementVisual(TitleText); titleTextVisual.CenterPoint = new Vector3(0, (float)TitleText.ActualHeight / 2, 0); titleTextVisual.StartAnimation("Scale.X", scaleAnimation); titleTextVisual.StartAnimation("Scale.Y", scaleAnimation); }
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); }
/// <summary> /// Create the _backVisual and the animations that drive it. /// </summary> /// <param name="scrollProperties">A property set who has Translation.Y specified - typically the return from ElementCompositionPreview.GetScrollViewerManipulationPropertySet(...).</param> /// <param name="maskedBrush">This is the brush that will be set on _frontVisual</param> private void InitializeBehindVisual(CompositionPropertySet scrollProperties, CompositionEffectBrush maskedBrush) { // // Create the _backVisual, set the brush on it, and attach it to the BackGrid. BackGrid is an empty grid // that is visually behind the profile background (the waves). Therefore, setting it as the // child visual on the BackGrid will put it behind all the scrollViewer content. // _backVisual = _compositor.CreateSpriteVisual(); _backVisual.Brush = maskedBrush; ElementCompositionPreview.SetElementChildVisual(BackGrid, _backVisual); // // This equation controls whether or not the FrontVisual is visibile via opacity. It uses a simple ternary operator // to pick between 100% and 0% opacity based on the position being after the crossover point. // _backVisual.Scale = new Vector3(_finalScaleAmount, _finalScaleAmount, 1); var scrollPropSet = scrollProperties.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var crossoverTranslation = ExpressionValues.Constant.CreateConstantScalar("CrossoverTranslation"); _behindOpacityExpression = EF.Conditional(-scrollPropSet.Translation.Y <= crossoverTranslation, 0, 1); // // "Terms" and explanation of the following expression: // // (initialOffset - scrollingProperties.Translation.Y) // // Since _backVisual is a child of the scroller, the initial position minus the scrolling offset keeps the content // in its original location. // // 2 * (CrossoverTranslation + scrollingProperties.Translation.Y) // // Since scrollingProperties.Translation.Y is negative when this expression is visibile, this term calculates the // distance past the crossover point and scales it. The scale causes the content to move faster than the scrolling. // Since this term evaluates to zero at the crossover point and the term above keeps the content from moving, when // the visibility swaps between frontVisual and backVisual, they are perfectly aligned. // var baseOffset = ExpressionValues.Constant.CreateConstantScalar("BaseOffset"); _behindTranslationExpression = (baseOffset - scrollPropSet.Translation.Y) + 2 * (crossoverTranslation + scrollPropSet.Translation.Y); }
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 Visual AddImage(CompositionSurfaceBrush imageBrush, NodeInfo nodeInfo, float defaultOpacity = 1.0f, bool applyDistanceEffects = true) { var sprite = _compositor.CreateSpriteVisual(); var size = ((CompositionDrawingSurface)imageBrush.Surface).Size; size.Width *= nodeInfo.Scale; size.Height *= nodeInfo.Scale; sprite.Size = new Vector2((float)size.Width, (float)size.Height); sprite.AnchorPoint = new Vector2(0.5f, 0.5f); sprite.Offset = nodeInfo.Offset; _worldContainer.Children.InsertAtTop(sprite); if (applyDistanceEffects) { // // Use an ExpressionAnimation to fade the image out when it goes too close or // too far away from the camera. // if (_opacityExpression == null) { var visualTarget = ExpressionValues.Target.CreateVisualTarget(); var world = _worldContainer.GetReference(); _opacityExpression = EF.Conditional( defaultOpacity * (visualTarget.Offset.Z + world.Offset.Z) > -200, 1 - EF.Clamp(visualTarget.Offset.Z + world.Offset.Z, 0, 300) / 300, EF.Clamp(visualTarget.Offset.Z + world.Offset.Z + 1300, 0, 300) / 300); } sprite.StartAnimation("Opacity", _opacityExpression); } sprite.Brush = imageBrush; return(sprite); }
private void AlbumList_Loaded(object sender, RoutedEventArgs e) { var ani = ConnectedAnimationService.GetForCurrentView().GetAnimation(Consts.ArtistPageInAnimation); if (ani != null) { ani.TryStart(Title, new UIElement[] { HeaderBG, Details }); } var scrollviewer = AlbumList.GetScrollViewer(); _scrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollviewer); _compositor = _scrollerPropertySet.Compositor; _props = _compositor.CreatePropertySet(); _props.InsertScalar("progress", 0); _props.InsertScalar("clampSize", (float)Title.ActualHeight + 64); _props.InsertScalar("scaleFactor", 0.5f); // 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 and start an ExpressionAnimation to track scroll progress over the desired distance ExpressionNode progressAnimation = EF.Clamp(-scrollingProperties.Translation.Y / ((float)Header.Height - clampSizeNode), 0, 1); _props.StartAnimation("progress", progressAnimation); // 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, scrollingProperties.Translation.Y, -(float)Header.Height + (float)Title.ActualHeight + 64); 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); var titleVisual = ElementCompositionPreview.GetElementVisual(Title); var titleshrinkVisual = ElementCompositionPreview.GetElementVisual(TitleShrink); var fixAnimation = EF.Conditional(progressNode < 1, -scrollingProperties.Translation.Y, (float)Header.Height - ((float)Title.ActualHeight + 64)); titleVisual.StartAnimation("Offset.Y", fixAnimation); titleshrinkVisual.StartAnimation("Offset.Y", fixAnimation); var detailsVisual = ElementCompositionPreview.GetElementVisual(Details); var opacityAnimation = EF.Clamp(1 - (progressNode * 8), 0, 1); detailsVisual.StartAnimation("Opacity", opacityAnimation); var headerbgVisual = ElementCompositionPreview.GetElementVisual(HeaderBG); var headerbgOverlayVisual = ElementCompositionPreview.GetElementVisual(HeaderBGOverlay); var bgBlurVisual = ElementCompositionPreview.GetElementVisual(BGBlur); var bgOpacityAnimation = EF.Clamp(1 - progressNode, 0, 1); var bgblurOpacityAnimation = EF.Clamp(progressNode, 0, 1); titleshrinkVisual.StartAnimation("Opacity", bgblurOpacityAnimation); titleVisual.StartAnimation("Opacity", bgOpacityAnimation); headerbgVisual.StartAnimation("Opacity", bgOpacityAnimation); headerbgOverlayVisual.StartAnimation("Opacity", bgOpacityAnimation); bgBlurVisual.StartAnimation("Opacity", bgblurOpacityAnimation); }
private void SamplePage_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e) { // Get the PropertySet that contains the scroll values from MyScrollViewer _scrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(MyScrollviewer); _compositor = _scrollerPropertySet.Compositor; Model = new LocalDataSource(); gridView.ItemsSource = Model.AggregateDataSources(new ObservableCollection <Thumbnail>[] { Model.Landscapes, Model.Nature, Model.Abstract }); // 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); }
private void SongsList_Loaded(object sender, RoutedEventArgs e) { var scrollviewer = Root; var _scrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollviewer); var _compositor = _scrollerPropertySet.Compositor; // Get references to our property sets for use with ExpressionNodes var scrollingProperties = _scrollerPropertySet.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var headerHeight = (float)(HeaderGroup.ActualHeight); var finalHeight = (float)TitleBG.ActualHeight; var progressAnimation = EF.Conditional(-scrollingProperties.Translation.Y > headerHeight, EF.Conditional(-scrollingProperties.Translation.Y > headerHeight + finalHeight, 0, -scrollingProperties.Translation.Y - headerHeight - finalHeight), -finalHeight); // 0~1 progressAnimation = (progressAnimation + finalHeight) / finalHeight; var toolbarVisual = ElementCompositionPreview.GetElementVisual(Toolbar); toolbarVisual.StartAnimation("Offset.Y", progressAnimation * 16 - 16); var offset = toolbarVisual.GetReference().GetScalarProperty("Offset.Y"); toolbarVisual.StartAnimation("Opacity", progressAnimation); var moving = 80f; var movingAnimation = EF.Conditional(-scrollingProperties.Translation.Y > moving, 0f, moving + scrollingProperties.Translation.Y); var horiMovingAni = EF.Clamp(-scrollingProperties.Translation.Y / moving, 0, 1); horiMovingAni = EF.Lerp(0, (float)(80f - ImageGrid.Height), horiMovingAni); var scaleAnimation = EF.Clamp(-scrollingProperties.Translation.Y / moving, 0, 1); var textScaleAnimation = EF.Lerp(1, (float)(ToolbarTitle.ActualHeight / TitleText.ActualHeight), scaleAnimation); var titleVisual = ElementCompositionPreview.GetElementVisual(Title); titleVisual.StartAnimation("Offset.Y", movingAnimation); titleVisual.StartAnimation("Offset.X", horiMovingAni); var titleTextVisual = ElementCompositionPreview.GetElementVisual(TitleText); titleTextVisual.CenterPoint = new Vector3(32f, (float)TitleText.ActualHeight / 2, 0); titleTextVisual.StartAnimation("Scale.X", textScaleAnimation); titleTextVisual.StartAnimation("Scale.Y", textScaleAnimation); var bgVisual = ElementCompositionPreview.GetElementVisual(TitleBG); bgVisual.StartAnimation("Opacity", scaleAnimation); var marginTop = (float)((TitleBG.ActualHeight - 80f) / 2); var imgMovingAnimation = EF.Conditional(-scrollingProperties.Translation.Y > (moving - marginTop), marginTop, moving + scrollingProperties.Translation.Y); var imageScaleAnimation = EF.Lerp(1, (float)(80f / ImageGrid.Height), scaleAnimation); var imageVisual = ElementCompositionPreview.GetElementVisual(ImageGrid); imageVisual.CenterPoint = new Vector3(32f, 0, 0); imageVisual.StartAnimation("Scale.X", imageScaleAnimation); imageVisual.StartAnimation("Scale.Y", imageScaleAnimation); imageVisual.StartAnimation("Offset.Y", imgMovingAnimation); }
private void ActivateGravityForce() { // // Setup the gravity+bounce inertia modifier. // var target = ExpressionValues.Target.CreateInteractionTrackerTarget(); var posY = target.Position.Y; var velY = target.PositionVelocityInPixelsPerSecond.Y; // // Gravity Force // // Adding a factor of 100 since -9.8 pixels / second ^2 is not very fast. var gravity = -9.8f * 100; // // Floor Force // // This is the force that resists gravity and causes the bouncing. It's defined as: // 1. Zero if above the floor, // 2. Equal and opposite to gravity if "on" the floor (1 pixel above floor or below), // 3. The effects of 2., plus a reflective force if the direction of motion is still downward and the tracker is below the floor. // This force is at its strongest (-1.8 * 100 * V) if the tracker is 5 or more // pixels below floor, and weakest (-1.0 * 100 * V) if the tracker is "at" the // floor. // // The amount the tracker is below the floor, capped to at most 5 below. var belowFloor = EF.Clamp(0, 0 - posY, 5); // The time slice our force engine uses. float dt = .01f; // // Defining bounce constants. // -2 would cause perfectly inellastic reflection, bouncing as high as it fell from. // -1 would cause perfectly ellastic reflection, freezing motion. // We want some bounce, but we also want the bouncing to decay, so choose // bounce factors between -1 and -2. // // Also, divide by the time slice width to make this reflective force apply entirely // all at once. // var weakestBounce = -1.1f / dt; var strongestBounce = -1.8f / dt; var floorForceExpression = EF.Conditional(posY < 1, -gravity, 0) + EF.Conditional(EF.And(velY < 0f, posY < 0f), EF.Lerp(weakestBounce, strongestBounce, belowFloor / 5) * velY, 0); // // Apply the forces to the modifier // var modifier = InteractionTrackerInertiaMotion.Create(_compositor); modifier.SetCondition((BooleanNode)true); modifier.SetMotion(gravity + floorForceExpression); _tracker.ConfigurePositionYInertiaModifiers(new InteractionTrackerInertiaModifier[] { modifier }); }
private void SongsList_Loaded(object sender, RoutedEventArgs e) { var scrollviewer = Root; var _scrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollviewer); var _compositor = _scrollerPropertySet.Compositor; // Get references to our property sets for use with ExpressionNodes var scrollingProperties = _scrollerPropertySet.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var headerHeight = (float)(HeaderGroup.ActualHeight); var finalHeight = (float)TitleBG.ActualHeight; var progressAnimation = EF.Conditional(-scrollingProperties.Translation.Y > headerHeight, EF.Conditional(-scrollingProperties.Translation.Y > headerHeight + finalHeight, 0, -scrollingProperties.Translation.Y - headerHeight - finalHeight), -finalHeight); // 0~1 progressAnimation = (progressAnimation + finalHeight) / finalHeight; var toolbarVisual = ElementCompositionPreview.GetElementVisual(Toolbar); toolbarVisual.StartAnimation("Offset.Y", progressAnimation * 16 - 16); var offset = toolbarVisual.GetReference().GetScalarProperty("Offset.Y"); toolbarVisual.StartAnimation("Opacity", progressAnimation); var moving = 80f; var movingAnimation = EF.Conditional(-scrollingProperties.Translation.Y > moving, 0f, moving + scrollingProperties.Translation.Y); var horiMovingAni = EF.Clamp(-scrollingProperties.Translation.Y / moving, 0, 1); horiMovingAni = EF.Lerp(0, (float)(80f - ImageGrid.Height), horiMovingAni); var scaleAnimation = EF.Clamp(-scrollingProperties.Translation.Y / moving, 0, 1); var textScaleAnimation = EF.Lerp(1, (float)(ToolbarTitle.ActualHeight / TitleText.ActualHeight), scaleAnimation); var titleVisual = ElementCompositionPreview.GetElementVisual(Title); titleVisual.StartAnimation("Offset.Y", movingAnimation); titleVisual.StartAnimation("Offset.X", horiMovingAni); var titleTextVisual = ElementCompositionPreview.GetElementVisual(TitleText); titleTextVisual.CenterPoint = new Vector3(32f, (float)TitleText.ActualHeight / 2, 0); titleTextVisual.StartAnimation("Scale.X", textScaleAnimation); titleTextVisual.StartAnimation("Scale.Y", textScaleAnimation); var bgVisual = ElementCompositionPreview.GetElementVisual(TitleBG); bgVisual.StartAnimation("Opacity", scaleAnimation); var marginTop = (float)((TitleBG.ActualHeight - 80f) / 2); var imgMovingAnimation = EF.Conditional(-scrollingProperties.Translation.Y > (moving - marginTop), marginTop, moving + scrollingProperties.Translation.Y); var imageScaleAnimation = EF.Lerp(1, (float)(80f / ImageGrid.Height), scaleAnimation); var imageVisual = ElementCompositionPreview.GetElementVisual(ImageGrid); imageVisual.CenterPoint = new Vector3(32f, 0, 0); imageVisual.StartAnimation("Scale.X", imageScaleAnimation); imageVisual.StartAnimation("Scale.Y", imageScaleAnimation); imageVisual.StartAnimation("Offset.Y", imgMovingAnimation); Task.Run(async() => { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () => { var ani = ConnectedAnimationService.GetForCurrentView().GetAnimation(Consts.ArtistPageInAnimation + "_1"); if (ani != null) { ani.TryStart(TitleText, new UIElement[] { Details }); } ani = ConnectedAnimationService.GetForCurrentView().GetAnimation(Consts.ArtistPageInAnimation + "_2"); if (ani != null) { ani.TryStart(Image); } }); }); }