Tag Archives: Composition APIs

Working with Brushes and Content – XAML and Visual Layer Interop, Part One

The Composition APIs empower Universal Windows Platform (UWP) developers to do beautiful and powerful things when they access the Visual Layer. In the Windows 10 Creators Update, we made working with the Visual Layer much easier with new, powerful APIs.

In this blog series, we’ll cover some of these improvements in the Creators Update and take a look at the following APIs:

  • In Part 1, today’s post:
    • XamlCompositionBrushBase – easily paint a XAML UIElement with a CompositionBrush
    • LoadedImageSurface – load an image easily and use with Composition APIs
  • In Part 2, we’ll look at:
    • XamlLights – apply lights to your XAML UI with a single line of XAML
    • PointerPositionPropertySet – create 60 FPS animations using pointer position, off the UI thread!
    • Enabling the Translation property – animate a XAML UI Element using Composition animation

If you’d like to review the previously available ElementCompositionPreview APIs, for example working with “hand-in” and “hand-out” Visuals, you can quickly catch up here.

Using XamlCompositionBrushBase

One of the benefits of the new Composition and XAML interop APIs is the ability to use a CompositionBrush to directly paint a XAML UIElement rather than being limited to XAML brushes only. For example, you can create a CompositionEffectBrush that applies a tinted blur to the content beneath and use the brush to paint a XAML rectangle that can be included in the XAML markup

This is accomplished by using the new abstract class XamlCompositionBrushBase available in the Creators Update. To use it, you subclass XamlCompositionBrushBase to create your own XAML Brush that can be used in your markup. As seen the example code below, the XamlCompositionBrushBase exposes a CompositionBrush property that you set with your effect (or any CompositionBrush) and it will be applied to the XAML element.

This effectively replaces the need to manually create SpriteVisuals with SetElementChild for most effect scenarios. In addition to needing less code to create and add an effect to the UI, using a Brush means you get the following added benefits for free:

  • Theming and Styling
  • Binding
  • Resource and Lifetime management
  • Layout aware
  • PointerEvents
  • HitTesting and other XAML-based advantages

Microsoft, as part of the Fluent Design System, has included a few Brushes in the Creators Update that leverage the features of XamlCompositionBrushBase:

Building a Custom Composition Brush

Let’s create a XamlCompositionBrush of our own to see how simple this can be.  Here’s what we’ll create:

To start, let’s create a very simple Brush that applies an InvertEffect to content under it. First, we’ll need to make a public sealed class that inherits from XamlCompositionBrushBase and override two methods:

  • OnConnected
  • OnDisconnected

Let’s dive into the code. First, create your Brush class, which inherits from XamlCompositionBrushBase:


public class InvertBrush : XamlCompositionBrushBase
{
    protected override void OnConnected()
    {
        if (CompositionBrush == null)
        {
            // 1 - Get the BackdropBrush, this gets what is behind the UI element
            var backdrop = Window.Current.Compositor.CreateBackdropBrush();

            // CompositionCapabilities: Are effects supported? If not, return.
            if (!CompositionCapabilities.GetForCurrentView().AreEffectsSupported())
            { 
               return;
            }
                
            // 2 - Create your Effect
            // New-up a Win2D InvertEffect and use the BackdropBrush as its Source
            // Note – To use InvertEffect, you'll need to add the Win2D NuGet package to your project (search NuGet for "Win2D.uwp")
            var invertEffect = new InvertEffect
            {
                Source = new CompositionEffectSourceParameter("backdrop")
            };

            // 3 - Set up the EffectFactory
            var effectFactory = Window.Current.Compositor.CreateEffectFactory(invertEffect);

            // 4 - Finally, instantiate the CompositionEffectBrush
            var effectBrush = effectFactory.CreateBrush();

            // and set the backdrop as the original source 
            effectBrush.SetSourceParameter("backdrop", backdrop);

            // 5 - Finally, assign your CompositionEffectBrush to the XCBB's CompositionBrush property
            CompositionBrush = effectBrush;
         }
    }

    protected override void OnDisconnected()
    {
        // Clean up
        CompositionBrush?.Dispose();
        CompositionBrush = null;
    }
}

There are a few things to call out in the code above.

  • In the OnConnected method, we get a CompositionBackdropBrush. This allows you to easily get the pixels behind the UIElement.
  • We use fallback protection. If the user’s device doesn’t have support for the effect(s), then just return.
  • Next, we create the InvertEffect and use the backdropBrush for the Effect’s Source.
  • Then, we pass the finished InvertEffect to the CompositionEffectFactory.
  • Finally, we get an EffectBrush from the factory and set the XamlCompositionBrushBase.CompositionBrush property with our newly created effectBrush.

Now you can use it in your XAML. For example, let’s apply it to a Grid on top of another Grid with a background image:


<Grid>
    <Grid.Background>
        <ImageBrush ImageSource="ms-appx:///Images/Background.png"/>
    </Grid.Background>
    <Grid Width="300" Height="300" 
               HorizontalAlignment="Center"
               VerticalAlignment="Center">
        <Grid.Background>
            <brushes:InvertBrush />
        </Grid.Background>
    </Grid>
</Grid>

Now that you know the basics of creating a brush, let’s build an animated effect brush next.

Creating a Brush with Animating Effects

Now that you see how simple it is to create a CompositionBrush, let’s create a brush that applies a TemeratureAndTint effect to an image and animate the Temperature value:

We start the same way we did with the simple InvertBrush, but this time we’ll add a DependencyProperty,  ImageUriString, so that we can load an image using LoadedImageSurface in the OnConnected method.

public sealed class ImageEffectBrush : XamlCompositionBrushBase
{
private LoadedImageSurface _surface;
private CompositionSurfaceBrush _surfaceBrush;
public static readonly DependencyProperty ImageUriStringProperty = DependencyProperty.Register(
"ImageUri",
typeof(string),
typeof(ImageEffectBrush),
new PropertyMetadata(string.Empty, OnImageUriStringChanged)
);
public string ImageUriString
{
get => (String)GetValue(ImageUriStringProperty);
set => SetValue(ImageUriStringProperty, value);
}
private static void OnImageUriStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var brush = (ImageEffectBrush)d;
// Unbox and update surface if CompositionBrush exists     
if (brush._surfaceBrush != null)
{
var newSurface = LoadedImageSurface.StartLoadFromUri(new Uri((String)e.NewValue));
brush._surface = newSurface;
brush._surfaceBrush.Surface = newSurface;
}
}
protected override void OnConnected()
{
// return if Uri String is null or empty
if (string.IsNullOrEmpty(ImageUriString))
return;
// Get a reference to the Compositor
Compositor compositor = Window.Current.Compositor;
// Use LoadedImageSurface API to get ICompositionSurface from image uri provided
_surface = LoadedImageSurface.StartLoadFromUri(new Uri(ImageUriString));
// Load Surface onto SurfaceBrush
_surfaceBrush = compositor.CreateSurfaceBrush(_surface);
_surfaceBrush.Stretch = CompositionStretch.UniformToFill;
// CompositionCapabilities: Are Tint+Temperature and Saturation supported?
bool usingFallback = !CompositionCapabilities.GetForCurrentView().AreEffectsSupported();
if (usingFallback)
{
// If Effects are not supported, Fallback to image without effects
CompositionBrush = _surfaceBrush;
return;
}
// Define Effect graph (add the Win2D.uwp NuGet package to get this effect)
IGraphicsEffect graphicsEffect = new SaturationEffect
{
Name = "Saturation",
Saturation = 0.3f,
Source = new TemperatureAndTintEffect
{
Name = "TempAndTint",
Temperature = 0,
Source = new CompositionEffectSourceParameter("Surface"),
}
};
// Create EffectFactory and EffectBrush 
CompositionEffectFactory effectFactory = compositor.CreateEffectFactory(graphicsEffect, new[] { "TempAndTint.Temperature" });
CompositionEffectBrush effectBrush = effectFactory.CreateBrush();
effectBrush.SetSourceParameter("Surface", _surfaceBrush);
// Set EffectBrush to paint Xaml UIElement
CompositionBrush = effectBrush;
// Trivial looping animation to demonstrate animated effect
ScalarKeyFrameAnimation tempAnim = compositor.CreateScalarKeyFrameAnimation();
tempAnim.InsertKeyFrame(0, 0);
tempAnim.InsertKeyFrame(0.5f, 1f);
tempAnim.InsertKeyFrame(1, 0);
tempAnim.Duration = TimeSpan.FromSeconds(5);
tempAnim.IterationBehavior = AnimationIterationBehavior.Count;
tempAnim.IterationCount = 10;
effectBrush.Properties.StartAnimation("TempAndTint.Temperature", tempAnim);
}
protected override void OnDisconnected()
{
// Dispose Surface and CompositionBrushes if XamlCompBrushBase is removed from tree
_surface?.Dispose();
_surface = null;
CompositionBrush?.Dispose();
CompositionBrush = null;
}
}

There are some new things here to call out that are different from the InvertBrush:

  • We use the new LoadedImageSurface API to easily load an image in the OnConnected method, but also when the ImageUriString value changes. Prior to Creators Update, this required a hand-in Visual (a SpriteVisual, painted with an EffectBrush, which was handed back into the XAML Visual Tree). See the LoadedImageSurface section later in this article for more details.
  • Notice that we gave the effects a Name value. In particular, TemperatureAndTintEffect, uses the name “TempAndTint.” This is required to animate properties as it is used for the reference to the effect in the AnimatableProperties array that is passed to the effect factory. Otherwise, you’ll encounter a “Malformed animated property name” error.
  • After we assign the CompositionBrush property, we created a simple looping animation to oscillate the value of the TempAndTint from 0 to 1 and back every 5 seconds.

Let’s take a look at an instance of this Brush in markup:

<Grid>
<Grid.Background>
<brushes:ImageEffectBrush ImageUriString="ms-appx:///Images/Background.png"/>
</Grid.Background>
</Grid>

For more information on using XamlCompositionBrushBase, see here. Now, let’s take a closer look at how easy it is now to bring in images to the Visual layer using LoadedImageSurface

Loading images with LoadedImageSurface

With the new LoadedImageSurface class, it’s never been easier to load an image and work with it in the visual layer. The class has the same codec support that Windows 10 has via the Windows Imaging Component (see full list here), thus it supports the following image file types:

  • Joint Photographic Experts Group (JPEG)
  • Portable Network Graphics (PNG)
  • Bitmap (BMP)
  • Graphics Interchange Format (GIF)
  • Tagged Image File Format (TIFF)
  • JPEG XR
  • Icons (ICO)

NOTE: When using an animated GIF, only the first frame will be used for the Visual, as animation is not supported in this scenario.

To load in an image, you can use one of the four factory methods:

As you can see there are two ways to load an image: with a Uri or a Stream. Additionally, you have an option to use an overload to set the size of the image (if you don’t pass in a Size, it will decode to the natural size).

CompositionSurfaceBrush imageBrush = compositor.CreateSurfaceBrush();
LoadedImageSurface loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Images/Photo.jpg"), new Size(200.0, 200.0));
imageBrush.Surface = loadedSurface;

This is very helpful when you need to load an image that will be used for your CompositionBrush (e.g. CompositionEffectBrush) or SceneLightingEffect (e.g. NormalMap for textures) as you no longer need to manually create a hand-in Visual (a SpriteVisual painted with an EffectBrush). In an upcoming post in this series, we will explore this further using NormalMap images with to create advanced lighting to create unique and compelling materials.

Using LoadedImageSurface with a Composition Island

LoadedImageSurface is also useful when loading an image onto a SpriteVisual inserted in XAML UI using ElementCompositionPreview. For this scenario, you can use the Loaded event to adjust the visual’s properties after the image has finished loading.

Here is an example of using LoadedImageSurface for a CompositionSurfaceBrush, then updating the SpriteVisual’s size with the image’s DecodedSize when the image is loaded:

private SpriteVisual spriteVisual;
private void LoadImage(Uri imageUri)
{
CompositionSurfaceBrush surfaceBrush = Window.Current.Compositor.CreateSurfaceBrush();
// You can load an image directly and set a SurfaceBrush's Surface property with it
var loadedImageSurface = LoadedImageSurface.StartLoadFromUri(imageUri);
loadedImageSurface.LoadCompleted += Load_Completed;
surfaceBrush.Surface = loadedImageSurface;
// We'll use a SpriteVisual for the hand-in visual
spriteVisual = Window.Current.Compositor.CreateSpriteVisual();
spriteVisual.Brush = surfaceBrush;
ElementCompositionPreview.SetElementChildVisual(MyCanvas, spriteVisual);
}
private void Load_Completed(LoadedImageSurface sender, LoadedImageSourceLoadCompletedEventArgs args)
{
if (args.Status == LoadedImageSourceLoadStatus.Success)
{
Size decodedSize = sender.DecodedSize;
spriteVisual.Size = new Vector2((float)decodedSize.Width, (float)decodedSize.Height);
}
}

There are some things you should be aware before getting started with LoadedImageSurface. This class makes working with images a lot easier, however you should understand the lifecycle and when images get decoded/sized. We recommend that you take a couple minutes and read the documentation before getting started.

Wrapping up

Using Composition features in your XAML markup is easier than ever. From painting your UIElements with CompositionBrushes and applying lighting, to smooth off-UIThread animations, the power of the Composition API is more accessible than ever.

In the next post, we’ll explore more new APIs like the new Translation property, using XamlLights in your XAML markup and how to create a custom light using the new PointerPositionPropertySet.

Resources

Smooth Interaction and Motion with the Visual Layer in Windows 10 Creators Update

The Composition APIs come with a robust animation engine that provides quick and fluid motion running in a separate process from your Universal Windows Platform (UWP) app. This ensures a consistent 60 frames per second when running your app on an IoT device as well as on a screaming gaming machine. It is, quite simply, fast. This is an essential capability for implementing the Fluent Design System which calls on us to create a sense of cinematic motion in our UWP apps.

The Composition APIs also provide something you probably have never had access to before: the ability to create high-performing, low-level manipulation-driven custom animations like the one shown above.  In the same way that we that want our visuals to be fast and smooth, we want our touch interactions to be sticky and responsive. Moving a visual with a finger or a digital pen should result in the visual element clinging to us no matter how fast we push and pull it across the display.

Even if a motion looks good, it also needs to feel good under the finger. It needs to maintain the illusion that we are interacting with a real object. It ought to possess the proper physics so that when we drag a visual across the screen and let go, it continues with the proper inertial movement. Similarly, user controls should provide the right amount of resistance when we pull and release them.

A fast and fluid animation system

The Visual Layer supports both keyframe animations as well as expression animations. If you have worked with XAML animations before, then you are probably already familiar with how keyframes work. In a keyframe animation, you set values for some property you want to change over time and also assign the duration for the change: in the example below, a start value, a middle value and then an ending value. The animation system will take care of tweening your animation – in other words, generating all the values between the ones you have explicitly specified based on the easing function you select. Whether Linear, or a Cubic Bezier, the animation system will use that to determine the values when interpolating.

CubicBezierEasingFunction cubicBezier = _compositor.CreateCubicBezierEasingFunction(new Vector2(.17f, .67f), new Vector2(1f, 1f));
ScalarKeyFrameAnimation blurAnimation = _compositor.CreateScalarKeyFrameAnimation();
blurAnimation.InsertKeyFrame(0.0f, 0.0f);
blurAnimation.InsertKeyFrame(0.5f, 100.0f);
blurAnimation.InsertKeyFrame(1.0f, 0.0f);
blurAnimation.Duration = TimeSpan.FromSeconds(4);
blurAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
_brush.StartAnimation("Blur.BlurAmount", blurAnimation);

A keyframe animation is a fire-and-forget mechanism that is time based. There are situations, however, when you need your animations to be coordinated and driving each other instead of simply moving in synchronized fashion.

In the animation above (source code), each gray gear is animated based on the animation of the gear preceding it. If the preceding gear suddenly goes faster or reverses direction, it forces the following gear to do the same. Keyframe animations can’t create motion effects that work in this way, but expression animations can. They are able to do so because, while keyframe animations are time based, expression animations are reference based.

The critical code that hooks up the gears for animation is found in the following code sample, which uses the new Expression Builder Library—an open source component released alongside of the Creators Update to construct expression animations. The expression below says that the animation should reference and be driven by the RotationAngleInDegrees property of the Visual that is indicated by the parameter “previousGear”. In the next line, the current Visual’s RotationAngleInDegrees property is finally animated based on the value referred to in an expression.

private void ConfigureGearAnimation(Visual currentGear, Visual previousGear)
{
// If rotation expression is null then create an expression of a gear rotating the opposite direction
var _rotateExpression = previousGear.GetReference().RotationAngleInDegrees;
// Start the animation based on the Rotation Angle in Degrees.
currentGear.StartAnimation("RotationAngleInDegrees", _rotateExpression);
}

But if an animation can be driven by another animation, you may be wondering, couldn’t we also drive an animation with something more concrete like user input? Why, yes. Yes, we can.

The beauty of the ScrollViewer ManipulationPropertySet

Driving an animation from a ScrollViewer using XAML-Composition interop is fairly easy. With just a few lines of code, you can enhance the visuals of a pre-existing ScrollViewer control with a CompositionAnimation by taking advantage of the GetScrollViewerManipulationPropertySet method on the ElementCompositionPreview class. Using an animation expression, you can tie your animation to the Position of your ScrollViewer component.

You would use this technique if you wanted to add a parallax effect to your XAML or to create a sticky header that stays in place as content scrolls beneath it. In the demo illustrated below (source code), a ScrollViewer is even used to drive a parallax effect on a ListView.

Adding parallax behavior to a XAML page can be accomplished in just a few lines.

// Note: We're not using the ScrollViewer's offset values directly. Instead, we use this PropertySet which holds the position values of the ScrollViewer in real-time.
var scrollPropSet = _scrollProperties.GetSpecializedReference<ManipulationPropertySetReferenceNode>();
var startOffset = ExpressionValues.Constant.CreateConstantScalar("startOffset", 0.0f);
var parallaxValue = 0.5f;
var itemHeight = 0.0f;
var parallax = (scrollPropSet.Translation.Y + startOffset - (0.5f * itemHeight));
_parallaxExpression = parallax * parallaxValue - parallax;
_parallaxExpression.SetScalarParameter("StartOffset", (float)args.ItemIndex * visual.Size.Y / 4.0f);
visual.StartAnimation("Offset.Y", _parallaxExpression);

The even more beautiful InteractionTracker

Driving expression animations with a ScrollViewer is extremely powerful, but what if you want to drive animations using touch gestures that aren’t limited to a pan/zoom gesture? Additionally, when using the ScrollViewer’s manipulations, your animations are linked to the UI thread responsiveness and can lose that buttery-smooth feel when the UI thread gets bogged down.

What if you want to pull items toward you with your finger, as in the demo below (source code), or animate multiple flying images across and into the screen as happens in the demo at the top of this post (source code)?

In order to achieve these effects, you would use the new InteractionTracker and VisualInteractionSource classes. InteractionTracker is a state machine that can be driven by active input. InteractionTracker also maintains a series of properties like Position and ScalePosition as part of maintaining the state. This is what you hook up to your animations. The VisualInteractionSource class, on the other hand, determines what kind of input you will use to drive your InteractionTracker and also when to start handling input (touch in particular).

The following sample code demonstrates a basic implementation of an InteractionTracker. The viewportVisual is simply the backing Visual for the root element on the page. You use this as the VisualInteractionSource for the tracker. In doing so, you specify that you are tracking X and Y manipulations. You also indicate that you want to track inertial movement.

_tracker = InteractionTracker.Create(_compositor);
var interactionSource = VisualInteractionSource.Create(viewportVisual);
interactionSource.PositionXSourceMode = InteractionSourceMode.EnabledWithInertia;
interactionSource.PositionYSourceMode = InteractionSourceMode.EnabledWithInertia;
_tracker.InteractionSources.Add(interactionSource);

Hooking the tracker up to an expression animation works basically the same way as hooking up a gear Visual to another gear Visual, as you did earlier. You call the CreateExpressionAnimation factory method on the current Compositor and reference the Position property of the tracker.

ar positionExpression = _compositor.CreateExpressionAnimation("-tracker.Position");
positionExpression.SetReferenceParameter("tracker", _tracker);
contentVisual.StartAnimation("Offset", positionExpression);

This code uses the InteractionTracker’s position to produce a smooth animation for the Offset of the Visual. You can also power your Blur and Opacity animations for your other Visuals as well. This will have a result where all three animations work together, with values based on how far the user dragged their finger, to result in an amazingly fluid visual experience. Run the demo and try it for yourself (source code).

Those are the basics of driving any animation from any input. What you do with this amazing new power is entirely up to you.

Wrapping up

Expression animations and Visual Layer Interactions are both topics that can become very deep very fast. To help you through these deeper waters, we highly recommend the following videos and articles:

Sweet UI made possible and easy with Windows.UI and the Windows 10 Creators Update

Since its original debut with the Windows 10 November 2015 update, Windows.UI.Composition has been empowering developers to build fast, beautiful, sweet user interfaces in UWP and has been providing enhancements with every subsequent Windows release. At Build 2017, we revealed what all of this continuous work has been leading up to: The Fluent Design System (aka ‘Project Neon’).

Moving from classic ‘Flat Design’ to Fluent Design requires the visual and performance capabilities that the Composition APIs offers along with the interop features that let you draw on this power from your XAML layer. In case you are not yet familiar with the concepts behind the Composition APIs, here’s a quick refresher on what the Composition APIs are all about.

The Windows.UI.Composition namespace allows Universal Windows Platform (UWP) developers to use a new Visual Layer that will get them closer to the metal, graphically speaking, while still using familiar technologies like XAML and C#. By getting closer to the metal, actually down to the system compositor level, developers are able to get great visual performance and custom UI experiences. By working through the XAML layer, developers get the ease of use they have come to expect out of UWP. This is basically a best of both worlds scenario that puts great responsibility in the developer’s hands. And with great responsibility, as we all know, comes great power.

So why do you need all these graphical and UX superpowers? In addition to giving pizazz to your UWP apps, access to the system compositor level also helps your users to accomplish their tasks faster and more fluidly. For instance, when you use Composition effects to blur a background in response to a click, you are focusing the user’s attention on her current task and removing distractions. This is the sort of subtle UI implementation that actually makes your user’s life easier – and it works best when your user doesn’t even know that you did anything for them. They are just left with the impression that your app is easy to use and feels fast, even if they can’t exactly put their finger on the reason.

The Visual family

To better understand the basic principles of Windows.UI.Composition, it’s important that we also introduce you to the visual family. In order to get fast and fluid effects, you need direct access to something called the system compositor (sometimes also referred to as the DWM). The system compositor is agnostic to the UI thread and doesn’t really care about being on the UI thread or blocking threads. Things happen very quickly at the system compositor level, where everything that is about to be sent to the display screen gets put together. This is also where you get to add additional effects if you want to just before shipping all your visuals to the display.

The visual family lives down at that compositor level where things happen rapidly. The visual family is made up of Visuals, ContainerVisuals and SpriteVisuals. The SpriteVisual class inherits from container visual, and the ContainerVisual class inherits from the base Visual class. There is also a Compositor class which acts as the senior member of the visual family. It quite literally creates visual objects if you need them and also manages the relationship between an application and the system compositor process.

The visual family is a lot of fun. Let’s say your XAML, many levels above, has a Grid object. That Grid will have a member of the visual family assigned to it. In technical parlance, we say that the Grid is backed by a visual. Once you grab hold of this backing visual, you can start to animate it using the composition animation system. If it is a ContainerVisual, then you can add additional visuals to it. Finally, you can also create sprite visuals, using the compositor factory class, in order to add brush effects to your visual using the Windows.UI.Composition effects system.

What’s new for sweet UI in the Windows 10 Creators Update

Several highly requested UI.Composition features have been added in the Creators Update to support fast and fluid UI as well as the Fluent Design System, for instance:

  • SVG support
  • Normal and Virtual Surfaces
  • Hover Interactions
  • Implicit Show and Hide
  • Expression Helpers
  • Offset stomping fix

At first these can seem like small disconnected improvements. Brought together, however, they will make creating beautiful UI both faster and easier.

XAML support for static SVG files

Vector images are often better for icons and logos because they can be resized without losing image quality. Before the Windows 10 Creators Update, however, vector graphics were not supported in XAML and working with iconography in UWP typically involved multiple versions of every image to adapt for multiple DPIs.  Now that that problem is solved, not only does XAML support static SVG files, but they also work with the Composition APIs.

Normal and virtual surfaces

The CompositionDrawingSurface has been a core component of the Composition APIs since the beginning, facilitating interop between XAML and Direct2D or Direct3D. The Creators Update is introducing the CompositionVirtualDrawingSurface for situations where only a portion of the content needs to be shown to the user at any given time. It basically bridges the concepts of graphics culling in video games and the development of infinite lists in desktop enterprise apps.

Independent hover interactions off the UI thread

One of the most powerful things about the Composition APIs is that they allow effects and animations to run independently of your main UI thread at 60 frames per second. With the Creators Update, this feature will also apply to hover animations in order to light up the many pointer activated effects that are a major part of fluent design.

There is also a subtle computer etiquette benefit to this new feature. Have you ever watched a busy animation play while your app’s UI was hanging and tried to move your mouse around in circles to try to make the animation go faster, but it has no effect? That is now a thing of the past.

Implicit show and hide

If you look at the code behind any UWP app, you will likely find that a large portion of UI code is devoted to setting visibility properties on UIElements in order to alternatively hide and show content. With this understanding, the Composition APIs now allow you to associate animations with your visual elements that are implicitly triggered when you hide or show them.

ElementCompositionPreview.SetImplicitShowAnimation(MainContent, mainContentShowAnimations);
ElementCompositionPreview.SetImplicitHideAnimation(MainContent, mainContentExitAnimation);

Implicit hide and show animations allow you to continue using this basic UI metaphor while also making it easier to create elegant visuals around them.

Expression helpers

Expression animations provide a way to create mathematical relationships between composition objects that can then be used to drive animations. The results of applying expression animations can often be breathtaking.

One piece of feedback we received about how we implemented expression animations is that it depends heavily on long strings of text like the following:

rotationAnimation.Expression = "ACos( ( (A.Offset.X * B.Offset.X) + (A.Offset.Y*B.Offset.Y) + (A.Offset.Z * B.Offset.Z) ) / ( Length(A.Offset) *  Length(B.Offset) ) )";
lineVisual.StartAnimation("RotationAngle", rotationAnimation);

The phrase “magic number” may even have been raised with respect to this. Just in time for the Creators Update, the Expression Builder Library is being introduced to provide you with type safety, IntelliSense and autocompletion as you create your own amazing expression animations.

Translation property

In earlier versions of the Composition APIs, there was a complication in the way UIElement properties were shared between the XAML layer and the Visual Layer that could cause the actual position of the visual to be overwritten or “stomped” in response to layout changes. While there was a workaround previously, there is now an actual fix with the new translation property. To prevent offset stomping, you now just need to enable the new Translation property through the ElementCompositionPreview class.

ElementCompositionPreview.SetIsTranslationEnabled(Rectangle1, true);

This is one of those issues that, if you’ve run into it before, you will feel a slight sense of relief. Just add a mental bookmark for yourself about the Translation property until you need to use it.

The sample gallery

The best way to deep dive into Windows.UI.Composition is by pulling down the sample code that the Composition team created and published to Github. The Windows UI Dev Labs samples, as they’re called, are extensive and visually rich. The samples extend from simple photo effects to complex parallax animations on XAML controls.

Don’t hesitate. It’s hard to really grasp the magnitude of the visual capabilities you are getting with Windows.UI.Composition until you see for yourself all that it empowers you to do.

Wrapping up

In addition to diving into the sample gallery on Github, which is highly recommended, you can also learn more about Windows Composition through the following articles, videos and blog posts.