PREREQUISITES:
- You need at least the Windows Anniversary Update to use composition API (build 10.0.14393.0)
- This post assumes you already know some basics about winComposition.
Parallax
You’re going to animate an image background behind a ListView.
The image background will move slower than the ListView and will have a superior border to prevent it to go off the screen.
Let’s look at the entire code to create a parallax scroll effect, and I’ll dive into it part by part:
NOTE: In order to make the embedded code lighter, there are missing parts like using declarations or constructors. If you want a full example, head to GitHub at the bottom of this post.
In your XAML you need an Image and a ListView. These two controls are necessary to get the effect.
First thing you want to do is to add a Loaded and an ImageOpened events, thus you’ll be sure to start manipulate the image after it’s loaded and opened. Same for the ListView, you’ll have to add a Loaded event.
ParallaxImage_Loaded
_backgroundVisual = ElementCompositionPreview.GetElementVisual(ParallaxImage);
In the Image Loaded event, you retrieve the image visual composition tree with GetElementVisual. When you have a component’s visual, you can add children to it. These children can be effects.
_backgroundCompositor = _backgroundVisual.Compositor;
When you get a reference to the page’s compositor object, you can use it to create effects. There is only one compositor object in a XAML application, so you can get it from any visual.
ListQuotes_Loaded
_ListQuotesScrollViewer = ListQuotes.GetChildOfType<ScrollViewer>();
GetChildOfType method finds a component’s child based on its type. You can use it to easily retrieve a ScrollViewer. Since this method doesn’t exist natively, you can import it to your code.
The ScrollViewer will be used to start animations on scrolling manipulations.
_ListQuotesScrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(_ListQuotesScrollViewer);
From the ScrollViewer component you get its PropertySet. A CompositionPropertySet provides the ability to insert key-value pairs or to retrieve a value for a given key. It’ll be useful in order to get the Y translation of the scroller.
ParallaxImage_ImageOpened
Next function is ParallaxImage_ImageOpened. In this function we’re just calling the AttachBackgroundParallax function. Now you’re sure you don’t manipulate the image before it’s been rendered.
AttachBackgroundParallax
double backgroundOffset = Math.Round(ParallaxImage.ActualHeight — ParallaxCanvas.ActualHeight);
This line calculates the hidden image’s portion. Remember that the image is hosted by a canvas, so its dimensions can exceed the device’s screen.
Calculating the image’s height will prevent the image to go off the screen.
Math.Round keeps the number’s integer part and ditches the decimal part. Animation expressions don’t accept decimal values.
After converting the image’s offset to a string value, use CreateExpressionAnimation method from the compositor.
An expression animation is an animation which uses a mathematical equation to calculate the value for an animating property. Unlike a KeyFrameAnimation (defined by a beginning, ending states and a duration time), the expression animation will be calculated according to an animating property.
In the example, the expression is defined by
Clamp(scroller.Translation.Y * parallaxFactor, -{0}, 999)
Clamp is a helper function defining a value between a minimum and a maximum range.
The Clamp function takes 3 parameters:
- A value to clamp
- The specified minimum range
- The specified maximum range
Here, the value is scroller.Translation.Y * parallaxFactor.
String.Format is used to set the minimum range to maxOffsetBottomToUp value. There’s a minus in front of the value because when the image moves from bottom to top, its offset goes from 0 to -X. Putting -{0} will give a positive value.
The maximum range is 999 but won’t go beyond 100 approximately due to the bouncing mechanism.
expression.SetScalarParameter(“parallaxFactor”, 0.03f);
Now you’re setting the parallaxFactor used in the expression animation. The ‘f’ character at the end means the value is normalized.
Choosing a value below 0 make the image background move slower than the ListView. Lower the value is, longer the scroll animation will be.
Note that we could’ve set the parallaxFactor value directly in the expression, but I’m just showing values can be replaced later in the string.
expression.SetReferenceParameter(“scroller”, _ListQuotesScrollerPropertySet);
Now you’re referencing the scroller word in the string as the CompositionPropertySet you got earlier. Thus, when the expression will try to evaluate scroller.Translation.Y, it’ll get the ScrollViewer’s vertical position.
_backgroundVisual.StartAnimation(“Offset.Y”, expression);
Finally, you bind the image background’s visual to the animation expression. Every time the scrollViewer’s Y position changes, the image’s Y position will change too.
The full example is available at my GitHub repository.