UWP — WinComposition: Parallax

rootasjey
4 min readOct 23, 2016

--

I’ve been interested in the new Windows.UI.Composition API since it’s been released.

There are examples demonstrating how to properly use it, but they’re are often too complicated for animations I want to achieve. So I decided to peel these complex samples into basic ones.

Source: Fré Sonneveld — Sa Pa, Vietnam

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.

Parallax peview (animation is much more fluid on a real device)

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:

XAML part to set up parallax effect
Code-behind (C#) to set up parallax effect

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.

A possible visual representation of an image hosted by a canvas

Calculating the image’s height will prevent the image to go off the screen.

Prevent the image from scrolling of 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.

Image’s vertical offset is a negative 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.

--

--