Partager via


Utilisation de la couche visuelle avec XAML

La plupart des applications qui consomment des fonctionnalités de couche visuelle utilisent XAML pour définir le contenu principal de l’interface utilisateur. Dans la mise à jour anniversaire Windows 10, il existe de nouvelles fonctionnalités dans l’infrastructure XAML et la couche visuelle qui facilitent la combinaison de ces deux technologies pour créer de superbes expériences utilisateur. Les fonctionnalités d’interopérabilité XAML et Visual Layer peuvent être utilisées pour créer des animations et des effets avancés non disponibles à l’aide d’API XAML seules. Cela inclut les éléments suivants :

  • Effets de pinceau comme le flou et le verre gelé
  • Effets d’éclairage dynamique
  • Animations pilotées par défilement et parallax
  • Animations d'agencement automatique
  • Ombres portées parfaites en pixels

Ces effets et animations peuvent être appliqués au contenu XAML existant. Vous n’avez donc pas à restructurer considérablement votre application XAML pour tirer parti des nouvelles fonctionnalités. Les animations de disposition, les ombres et les effets flous sont abordés dans la section Recettes ci-dessous. Pour obtenir un exemple de code qui implémente la parallaxe, consultez l’exemple ParallaxingListItems. Le référentiel WindowsCompositionSamples contient également plusieurs autres exemples d’implémentation d’animations, d’ombres et d’effets.

Classe XamlCompositionBrushBase

XamlCompositionBrush fournit une classe de base pour les pinceaux XAML qui peignent une zone avec un CompositionBrush. Cela peut être utilisé pour appliquer facilement des effets de composition tels que du flou ou du verre gelé aux éléments d’interface utilisateur XAML.

Pour plus d’informations sur l’utilisation des pinceaux avec l’interface utilisateur XAML, consultez la section Pinceaux .

Pour obtenir des exemples de code, consultez la page de référence pour XamlCompositionBrushBase.

Classe XamlLight

XamlLight fournit une classe de base pour les effets d’éclairage XAML qui éclairent dynamiquement une zone avec un CompositionLight.

Consultez la section Éclairage pour plus d’informations sur l’utilisation des lumières, notamment sur les éléments d’interface utilisateur XAML d’éclairage.

Pour obtenir des exemples de code, consultez la page de référence pour XamlLight.

Classe ElementCompositionPreview

ElementCompositionPreview est une classe statique qui fournit des fonctionnalités d’interopérabilité XAML et Visual Layer. Pour obtenir une vue d’ensemble de la couche visuelle et de ses fonctionnalités, consultez Couche visuelle. La classe ElementCompositionPreview fournit les méthodes suivantes :

  • GetElementVisual: Obtenir un visuel de type « présentation » utilisé pour afficher cet élément
  • SetElementChildVisual: définit un visuel « handin » comme dernier enfant de l’arborescence visuelle de cet élément. Ce visuel se superposera au reste de l'élément.
  • GetElementChildVisual : Récupérer l’ensemble visuel à l’aide de SetElementChildVisual
  • GetScrollViewerManipulationPropertySet : Obtenir un objet qui peut être utilisé pour créer des animations 60fps en fonction du décalage de défilement dans un ScrollViewer

Remarques sur ElementCompositionPreview.GetElementVisual

ElementCompositionPreview.GetElementVisual retourne un visuel « délégué » utilisé pour afficher le UIElementdonné. Les propriétés telles que Visual.Opacity, Visual.Offset et Visual.Size sont définies par l’infrastructure XAML en fonction de l’état de UIElement. Cela permet d'appliquer des techniques comme les animations de repositionnement implicites (voir Recettes).

Notez que, comme décalage et taille sont définies par la disposition du cadre XAML, les développeurs doivent être prudents lors de la modification ou de l’animation de ces propriétés. Les développeurs doivent uniquement modifier ou animer Offset lorsque le coin supérieur gauche de l’élément a la même position que celui de son parent dans la disposition. La taille ne doit généralement pas être modifiée, mais l’accès à la propriété peut être utile. Par exemple, les exemples Drop Shadow et Frosted Glass ci-dessous utilisent la taille d’un visuel de support de présentation comme entrée pour une animation.

En guise d’avertissement supplémentaire, les propriétés mises à jour du "handout Visual" ne sont pas reflétées dans l’UIElement correspondant. Par exemple, définir UIElement.Opacity sur 0,5 règliera l’opacité du visuel de la présentation correspondante sur 0,5. Toutefois, la définition de la opacité du visuel de document sur 0,5 entraîne l’affichage du contenu à 50% opacité, mais ne modifie pas la valeur de la propriété Opacity de l’interface utilisateur correspondante.

Exemple de décalage de l'animation

Incorrect

<Border>
      <Image x:Name="MyImage" Margin="5" />
</Border>
// Doesn’t work because Image has a margin!
ElementCompositionPreview.GetElementVisual(MyImage).StartAnimation("Offset", parallaxAnimation);

C’est bien ça

<Border>
    <Canvas Margin="5">
        <Image x:Name="MyImage" />
    </Canvas>
</Border>
// This works because the Canvas parent doesn’t generate a layout offset.
ElementCompositionPreview.GetElementVisual(MyImage).StartAnimation("Offset", parallaxAnimation);

Méthode ElementCompositionPreview.SetElementChildVisual

ElementCompositionPreview.SetElementChildVisual permet au développeur de fournir un Visual « handin » qui apparaîtra dans l'arborescence visuelle d’un élément. Cela permet aux développeurs de créer un « Île de composition » où le contenu visuel peut apparaître à l’intérieur d’une interface utilisateur XAML. Les développeurs devraient être prudents quant à l'utilisation de cette technique, car le contenu basé sur Visual ne bénéficiera pas des mêmes garanties d'accessibilité et d'expérience utilisateur que le contenu XAML. Par conséquent, il est généralement recommandé d’utiliser cette technique uniquement si nécessaire pour implémenter des effets personnalisés tels que ceux trouvés dans la section Recettes ci-dessous.

méthodes GetAlphaMask

Image, TextBlock et Shape implémentent chacune une méthode appelée GetAlphaMask qui retourne un Objet CompositionBrush représentant une image de nuances de gris avec la forme de l’élément. Cette CompositionBrush peut servir d’entrée pour un Composition DropShadow, afin que l’ombre puisse refléter la forme de l’élément au lieu d’un rectangle. Cela permet d'obtenir des ombres parfaites et basées sur les contours pour le texte, les images avec canal alpha et les formes. Consultez Drop Shadow ci-dessous pour obtenir un exemple de cette API.

Recettes

Repositionner l’animation

À l’aide des animations implicites de composition, un développeur peut animer automatiquement les modifications dans la disposition d’un élément par rapport à son parent. Par exemple, si vous modifiez la marge du bouton ci-dessous, elle s’anime automatiquement à sa nouvelle position de disposition.

Vue d’ensemble de l’implémentation

  1. Obtenez le document Visual pour l'élément cible
  2. Créer un ImplicitAnimationCollection qui anime automatiquement les modifications dans la propriété Offset
  3. Associer le ImplicitAnimationCollection au Visual de stockage
<Button x:Name="RepositionTarget" Content="Click Me" />
public MainPage()
{
    InitializeComponent();
    InitializeRepositionAnimation(RepositionTarget);
}

private void InitializeRepositionAnimation(UIElement repositionTarget)
{
    var targetVisual = ElementCompositionPreview.GetElementVisual(repositionTarget);
    Compositor compositor = targetVisual.Compositor;

    // Create an animation to animate targetVisual's Offset property to its final value
    var repositionAnimation = compositor.CreateVector3KeyFrameAnimation();
    repositionAnimation.Duration = TimeSpan.FromSeconds(0.66);
    repositionAnimation.Target = "Offset";
    repositionAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue");

    // Run this animation when the Offset Property is changed
    var repositionAnimations = compositor.CreateImplicitAnimationCollection();
    repositionAnimations["Offset"] = repositionAnimation;

    targetVisual.ImplicitAnimations = repositionAnimations;
}

Ombre portée

Appliquez une ombre déroulante parfaite en pixels à un UIElement, par exemple un Ellipse contenant une image. Étant donné que l’ombre nécessite un SpriteVisual créé par l’application, nous devons créer un élément hôte qui contiendra le SpriteVisual à l’aide de ElementCompositionPreview.SetElementChildVisual.

Vue d’ensemble de l’implémentation

  1. Récupérer le document visuel pour l’élément hôte
  2. Créer un Windows.UI.Composition DropShadow
  3. Configurer dropShadow pour obtenir sa forme à partir de l’élément cible via un masque
    • DropShadow est rectangulaire par défaut. Cela n’est donc pas nécessaire si la cible est rectangulaire
  4. Attachez une ombre à un nouvel élément SpriteVisual , et définissez le SpriteVisual comme enfant de l'élément hôte.
  5. Lier la taille du SpriteVisual à la taille de l’hôte à l’aide d’un ExpressionAnimation
<Grid Width="200" Height="200">
    <Canvas x:Name="ShadowHost" />
    <Ellipse x:Name="CircleImage">
        <Ellipse.Fill>
            <ImageBrush ImageSource="Assets/Images/2.jpg" Stretch="UniformToFill" />
        </Ellipse.Fill>
    </Ellipse>
</Grid>
public MainPage()
{
    InitializeComponent();
    InitializeDropShadow(ShadowHost, CircleImage);
}

private void InitializeDropShadow(UIElement shadowHost, Shape shadowTarget)
{
    Visual hostVisual = ElementCompositionPreview.GetElementVisual(shadowHost);
    Compositor compositor = hostVisual.Compositor;

    // Create a drop shadow
    var dropShadow = compositor.CreateDropShadow();
    dropShadow.Color = Color.FromArgb(255, 75, 75, 80);
    dropShadow.BlurRadius = 15.0f;
    dropShadow.Offset = new Vector3(2.5f, 2.5f, 0.0f);
    // Associate the shape of the shadow with the shape of the target element
    dropShadow.Mask = shadowTarget.GetAlphaMask();

    // Create a Visual to hold the shadow
    var shadowVisual = compositor.CreateSpriteVisual();
    shadowVisual.Shadow = dropShadow;

    // Add the shadow as a child of the host in the visual tree
   ElementCompositionPreview.SetElementChildVisual(shadowHost, shadowVisual);

    // Make sure size of shadow host and shadow visual always stay in sync
    var bindSizeAnimation = compositor.CreateExpressionAnimation("hostVisual.Size");
    bindSizeAnimation.SetReferenceParameter("hostVisual", hostVisual);

    shadowVisual.StartAnimation("Size", bindSizeAnimation);
}

Les deux listes suivantes montrent les équivalents C++/WinRT et C++/CX du code C# précédent à l’aide de la même structure XAML.

#include <winrt/Windows.UI.Composition.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Hosting.h>
#include <winrt/Windows.UI.Xaml.Shapes.h>
...
MainPage()
{
    InitializeComponent();
    InitializeDropShadow(ShadowHost(), CircleImage());
}

int32_t MyProperty();
void MyProperty(int32_t value);

void InitializeDropShadow(Windows::UI::Xaml::UIElement const& shadowHost, Windows::UI::Xaml::Shapes::Shape const& shadowTarget)
{
    auto hostVisual{ Windows::UI::Xaml::Hosting::ElementCompositionPreview::GetElementVisual(shadowHost) };
    auto compositor{ hostVisual.Compositor() };

    // Create a drop shadow
    auto dropShadow{ compositor.CreateDropShadow() };
    dropShadow.Color(Windows::UI::ColorHelper::FromArgb(255, 75, 75, 80));
    dropShadow.BlurRadius(15.0f);
    dropShadow.Offset(Windows::Foundation::Numerics::float3{ 2.5f, 2.5f, 0.0f });
    // Associate the shape of the shadow with the shape of the target element
    dropShadow.Mask(shadowTarget.GetAlphaMask());

    // Create a Visual to hold the shadow
    auto shadowVisual = compositor.CreateSpriteVisual();
    shadowVisual.Shadow(dropShadow);

    // Add the shadow as a child of the host in the visual tree
    Windows::UI::Xaml::Hosting::ElementCompositionPreview::SetElementChildVisual(shadowHost, shadowVisual);

    // Make sure size of shadow host and shadow visual always stay in sync
    auto bindSizeAnimation{ compositor.CreateExpressionAnimation(L"hostVisual.Size") };
    bindSizeAnimation.SetReferenceParameter(L"hostVisual", hostVisual);

    shadowVisual.StartAnimation(L"Size", bindSizeAnimation);
}
#include "WindowsNumerics.h"

MainPage::MainPage()
{
    InitializeComponent();
    InitializeDropShadow(ShadowHost, CircleImage);
}

void MainPage::InitializeDropShadow(Windows::UI::Xaml::UIElement^ shadowHost, Windows::UI::Xaml::Shapes::Shape^ shadowTarget)
{
    auto hostVisual = Windows::UI::Xaml::Hosting::ElementCompositionPreview::GetElementVisual(shadowHost);
    auto compositor = hostVisual->Compositor;

    // Create a drop shadow
    auto dropShadow = compositor->CreateDropShadow();
    dropShadow->Color = Windows::UI::ColorHelper::FromArgb(255, 75, 75, 80);
    dropShadow->BlurRadius = 15.0f;
    dropShadow->Offset = Windows::Foundation::Numerics::float3(2.5f, 2.5f, 0.0f);
    // Associate the shape of the shadow with the shape of the target element
    dropShadow->Mask = shadowTarget->GetAlphaMask();

    // Create a Visual to hold the shadow
    auto shadowVisual = compositor->CreateSpriteVisual();
    shadowVisual->Shadow = dropShadow;

    // Add the shadow as a child of the host in the visual tree
    Windows::UI::Xaml::Hosting::ElementCompositionPreview::SetElementChildVisual(shadowHost, shadowVisual);

    // Make sure size of shadow host and shadow visual always stay in sync
    auto bindSizeAnimation = compositor->CreateExpressionAnimation("hostVisual.Size");
    bindSizeAnimation->SetReferenceParameter("hostVisual", hostVisual);

    shadowVisual->StartAnimation("Size", bindSizeAnimation);
}

Verre gelé

Créez un effet qui flout et teinte le contenu d’arrière-plan. Notez que les développeurs doivent installer le package NuGet Win2D pour utiliser des effets. Pour obtenir des instructions d’installation, consultez la page d’accueil Win2D .

Vue d’ensemble de l’implémentation

  1. Obtenir le document visual pour l’élément hôte
  2. Créer une arborescence d’effets flou à l’aide de Win2D et CompositionEffectSourceParameter
  3. Créer un CompositionEffectBrush à partir de l’arborescence d’effets
  4. Définissez l’entrée du CompositionEffectBrush sur un CompositionBackdropBrush, ce qui permet d’appliquer un effet au contenu derrière un SpriteVisual
  5. Définissez le CompositionEffectBrush en tant que contenu d’un nouveau SpriteVisual, puis définissez le SpriteVisual comme enfant de l’élément hôte. Vous pouvez également utiliser un XamlCompositionBrushBase.
  6. Lier la taille du SpriteVisual à la taille de l’hôte à l’aide d’un ExpressionAnimation
<Grid Width="300" Height="300" Grid.Column="1">
    <Image
        Source="Assets/Images/2.jpg"
        Width="200"
        Height="200" />
    <Canvas
        x:Name="GlassHost"
        Width="150"
        Height="300"
        HorizontalAlignment="Right" />
</Grid>
public MainPage()
{
    InitializeComponent();
    InitializeFrostedGlass(GlassHost);
}

private void InitializeFrostedGlass(UIElement glassHost)
{
    Visual hostVisual = ElementCompositionPreview.GetElementVisual(glassHost);
    Compositor compositor = hostVisual.Compositor;

    // Create a glass effect, requires Win2D NuGet package
    var glassEffect = new GaussianBlurEffect
    { 
        BlurAmount = 15.0f,
        BorderMode = EffectBorderMode.Hard,
        Source = new ArithmeticCompositeEffect
        {
            MultiplyAmount = 0,
            Source1Amount = 0.5f,
            Source2Amount = 0.5f,
            Source1 = new CompositionEffectSourceParameter("backdropBrush"),
            Source2 = new ColorSourceEffect
            {
                Color = Color.FromArgb(255, 245, 245, 245)
            }
        }
    };

    //  Create an instance of the effect and set its source to a CompositionBackdropBrush
    var effectFactory = compositor.CreateEffectFactory(glassEffect);
    var backdropBrush = compositor.CreateBackdropBrush();
    var effectBrush = effectFactory.CreateBrush();

    effectBrush.SetSourceParameter("backdropBrush", backdropBrush);

    // Create a Visual to contain the frosted glass effect
    var glassVisual = compositor.CreateSpriteVisual();
    glassVisual.Brush = effectBrush;

    // Add the blur as a child of the host in the visual tree
    ElementCompositionPreview.SetElementChildVisual(glassHost, glassVisual);

    // Make sure size of glass host and glass visual always stay in sync
    var bindSizeAnimation = compositor.CreateExpressionAnimation("hostVisual.Size");
    bindSizeAnimation.SetReferenceParameter("hostVisual", hostVisual);

    glassVisual.StartAnimation("Size", bindSizeAnimation);
}

Ressources additionnelles