Freigeben über


Verwenden der visuellen Ebene mit WinUI-XAML

Die meisten WinUI- und Windows App SDK-Apps, die Visual Layer-Funktionen nutzen, verwenden XAML, um den Hauptinhalt der Benutzeroberfläche zu definieren. WinUI bietet Features im XAML-Framework und der visuellen Ebene, die es einfacher machen, diese beiden Technologien zu kombinieren, um beeindruckende Benutzeroberflächen zu schaffen. Xaml- und Visual Layer-Interoperabilitätsfunktionen können verwendet werden, um erweiterte Animationen und Effekte zu erstellen, die nicht allein mit XAML-APIs verfügbar sind. Dazu gehören:

  • Pinseleffekte wie Weichzeichner und Frostglas
  • Dynamische Beleuchtungseffekte
  • Bildlaufgesteuerte Animationen und Parallax-Effekte
  • Automatische Layoutanimationen
  • Pixelgenaue Schlagschatten

Diese Effekte und Animationen können auf vorhandene XAML-Inhalte angewendet werden, sodass Sie Ihre WinUI-App nicht erheblich umstrukturieren müssen, um die Funktionalität zu nutzen. Layoutanimationen, Schatten und Weichzeichnereffekte werden im Abschnitt "Rezepte" unten behandelt. Ein Codebeispiel zur Implementierung von Parallax finden Sie im ParallaxingListItems-Beispiel. Das WindowsCompositionSamples-Repository enthält auch mehrere weitere Beispiele für die Implementierung von Animationen, Schatten und Effekten.

Die XamlCompositionBrushBase-Klasse

Microsoft.UI.Xaml.Media.XamlCompositionBrushBase stellt eine Basisklasse für XAML-Pinsel bereit, die einen Bereich mit einem CompositionBrush zeichnen. Dies kann dazu verwendet werden, Zusammensetzungseffekte wie Unschärfe oder Frostglas einfach auf XAML-UI-Elemente anzuwenden.

Weitere Informationen zur Verwendung von Pinseln mit XAML-UI finden Sie im Abschnitt "Brushes ".

Codebeispiele finden Sie auf der Referenzseite für XamlCompositionBrushBase.

Die XamlLight-Klasse

Microsoft.UI.Xaml.Media.XamlLight stellt eine Basisklasse für XAML-Beleuchtungseffekte bereit, die einen Bereich mit einem CompositionLight dynamisch beleuchten.

Weitere Informationen zur Verwendung von Lichtern, einschließlich XAML-UI-Elementen für beleuchtung, finden Sie im Abschnitt "Beleuchtung ".

Codebeispiele finden Sie auf der Referenzseite für XamlLight.

Arbeiten mit WinUI-XAML

ElementCompositionPreview ist eine statische Klasse, die XAML- und Visual Layer-Interoperabilitätsfunktionen bereitstellt. Eine Übersicht über die visuelle Ebene und deren Funktionalität finden Sie unter Visual Layer. Die ElementCompositionPreview-Klasse stellt die folgenden WinUI-Interopmethoden bereit:

  • GetElementVisual: Abrufe ein Visual, das für das Rendern dieses Elements verwendet wird
  • SetElementChildVisual: Legt ein "handin"-Visual als letztes untergeordnetes Element der visuellen Struktur dieses Elements fest. Dieses visuelle Element wird über dem Rest des Elements gezeichnet.
  • GetElementChildVisual: Abrufen des visuellen Satzes mithilfe von SetElementChildVisual
  • GetScrollViewerManipulationPropertySet: Abrufen eines Objekts, das zum Erstellen von 60fps-Animationen basierend auf dem Bildlaufoffset in einem ScrollViewer verwendet werden kann

GetElementVisual

ElementCompositionPreview.GetElementVisual gibt ein "Handzettel"-Visual zurück, das zum Rendern des angegebenen UIElements verwendet wird. Eigenschaften wie Visual.Opacity, Visual.Offset und Visual.Size werden vom XAML-Framework basierend auf dem Zustand des UIElements festgelegt. Dies ermöglicht Techniken wie implizite Neupositionierungsanimationen (siehe Rezepte).

Da Offset und Größe als Ergebnis des XAML-Frameworklayouts festgelegt werden, sollten Entwickler beim Ändern oder Animieren dieser Eigenschaften vorsichtig sein. Entwickler sollten den Offset nur ändern oder animieren, wenn die obere linke Ecke des Elements dieselbe Position wie die des übergeordneten Elements im Layout aufweist. Die Größe sollte im Allgemeinen nicht geändert werden, aber der Zugriff auf die Eigenschaft kann nützlich sein. In den folgenden Beispielen "Drop Shadow" und "Frosted Glass" wird beispielsweise die Größe eines Handzettel-Visuelles als Eingabe für eine Animation verwendet.

Als zusätzliche Einschränkung werden aktualisierte Eigenschaften der Handout-Visuals nicht im entsprechenden UIElement widergespiegelt. Wenn Sie beispielsweise UIElement.Opacity auf 0,5 festlegen, wird die Opacity des entsprechenden Visuals auf 0,5 festgelegt. Wenn Sie jedoch die Deckkraft des Visuals des Handzettels auf 0,5 festlegen, wird der Inhalt mit einer Deckkraft von 50% angezeigt, ändert jedoch nicht den Wert der Opacity-Eigenschaft des entsprechenden UIElements.

Beispiel für Offsetanimation

Unrichtig

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

Richtig

<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);

SetElementChildVisual

Mit "ElementCompositionPreview.SetElementChildVisual " kann der Entwickler ein "handin"-Visual bereitstellen, das als Teil der visuellen Struktur eines Elements angezeigt wird. Auf diese Weise können Entwickler eine "Composition Island" erstellen, in der visuelle Inhalte in einer XAML-Benutzeroberfläche angezeigt werden können. Entwickler sollten bei der Verwendung dieser Technik vorsichtig sein, da visuelle Inhalte nicht über die gleichen Barrierefreiheits- und Benutzerfreundlichkeitsgarantien für XAML-Inhalte verfügen. Daher wird im Allgemeinen empfohlen, diese Technik nur bei Bedarf zum Implementieren von benutzerdefinierten Effekten wie denen im Abschnitt "Rezepte" unten zu verwenden.

GetAlphaMask-Methoden

Image, TextBlock und Shape implementieren jeweils eine Methode namens "GetAlphaMask ", die einen CompositionBrush zurückgibt, der ein Graustufenbild mit der Form des Elements darstellt. Dieser CompositionBrush kann als Eingabe für ein Composition DropShadow dienen, sodass der Schatten die Form des Elements anstelle eines Rechtecks widerspiegeln kann. Dies ermöglicht pixelgenaue, konturbasierte Schatten für Text, Bilder mit Alpha und Formen. Ein Beispiel für diese API finden Sie unten unter "Schlagschatten ".

Rezepte

Animation neu anordnen

Mithilfe impliziter Kompositionsanimationen kann ein Entwickler änderungen im Layout eines Elements automatisch relativ zum übergeordneten Element animieren. Wenn Sie beispielsweise den Rand der schaltfläche unten ändern, wird sie automatisch an die neue Layoutposition animiert.

Übersicht zur Umsetzung

  1. Laden Sie das Handbuch Visual für das Zielelement herunter.
  2. Erstellen einer ImplicitAnimationCollection , die Änderungen in der Offset-Eigenschaft automatisch animiert
  3. Verknüpfung der ImplicitAnimationCollection mit dem zugrunde liegenden Visual
<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;
}

Schlagschatten

Wenden Sie einen pixelgenauen Schlagschatten auf ein UIElement an, z. B. eine Ellipse , die ein Bild enthält. Da für den Schatten ein von der App erstelltes SpriteVisual erforderlich ist, müssen wir ein "host"-Element erstellen, das das SpriteVisual mit ElementCompositionPreview.SetElementChildVisual enthält.

Übersicht zur Umsetzung

  1. Holen Sie sich das Handout für das Hostelement.
  2. Microsoft.UI.Composition DropShadow erstellen
  3. Konfigurieren Sie die DropShadow, damit seine Form über eine Maske vom Zielelement übernommen wird.
    • DropShadow ist standardmäßig rechteckig, daher ist dies nicht erforderlich, wenn das Ziel rechteckig ist.
  4. Anfügen eines Schattens an ein neues SpriteVisual-Element und Festlegen des SpriteVisual als untergeordnetes Element des Hostelements
  5. Größe des SpriteVisual mit der Größe des Hosts mittels einer ExpressionAnimation binden
<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);
}

Die folgende Auflistung zeigt die C++/WinRT-Entsprechung des vorherigen C#-Codes mit derselben XAML-Struktur.

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

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

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

    // Create a drop shadow
    auto dropShadow{ compositor.CreateDropShadow() };
    dropShadow.Color(Microsoft::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
    Microsoft::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);
}

Milchglas

Erstellen Sie einen Effekt, der Hintergrundinhalte weichzeichnet und färbt. Beachten Sie, dass Entwickler das Win2D NuGet-Paket installieren müssen, um Effekte zu verwenden. Installationsanweisungen finden Sie auf der Win2D-Homepage .

Übersicht zur Umsetzung

  1. Das Handout Visual für das Hostelement abrufen
  2. Erstellen Sie einen Weichzeichnereffektbaum mit Win2D und CompositionEffectSourceParameter
  3. Erstellen Sie einen CompositionEffectBrush basierend auf dem Effektbaum
  4. Legen Sie die Eingabe von CompositionEffectBrush auf einen CompositionBackdropBrush fest, wodurch ein Effekt auf den Inhalt hinter einem SpriteVisual angewendet werden kann
  5. Legen Sie den CompositionEffectBrush als Inhalt eines neuen SpriteVisual fest, und legen Sie SpriteVisual als untergeordnetes Element des Hostelements fest. Alternativ können Sie eine XamlCompositionBrushBase verwenden.
  6. Binden Sie die Größe des SpriteVisual an die des Hosts mithilfe einer 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);
}

Zusätzliche Ressourcen