Verwenden der visuellen Ebene mit XAML
Die meisten Apps, die Visual Layer-Funktionen nutzen, verwenden XAML, um den Hauptinhalt der Benutzeroberfläche zu definieren. Im Windows 10 Anniversary Update gibt es neue 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. Dies umfasst:
- Pinseleffekte wie Weichzeichner und Frostglas
- Dynamische Beleuchtungseffekte
- Bildlaufgesteuerte Animationen und Parallax
- Automatische Layoutanimationen
- Pixelgenaue Schlagschatten
Diese Effekte und Animationen können auf vorhandene XAML-Inhalte angewendet werden, sodass Sie Ihre XAML-App nicht erheblich neu strukturieren müssen, um die neuen Funktionen nutzen zu können. 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
XamlCompositionBrush stellt eine Basisklasse für XAML-Pinsel bereit, die einen Bereich mit einem CompositionBrush zeichnen. Dies kann verwendet werden, um Kompositionseffekte wie Weichzeichner 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
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.
Die ElementCompositionPreview-Klasse
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 Methoden bereit:
- GetElementVisual: Abrufen eines "Handzettel"-Visuellen Elements, das zum 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
Hinweise zu ElementCompositionPreview.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 des Handzettel-Visuals nicht in das entsprechende UIElement wiedergegeben. Wenn Sie beispielsweise UIElement.Opacity auf 0,5 festlegen, wird die Opacity des entsprechenden Handzettels von Visual auf 0,5 festgelegt. Wenn Sie jedoch die Deckkraft des Handzettels von Visual auf 0,5 festlegen, wird der Inhalt bei 50 % Deckkraft angezeigt, ändert jedoch nicht den Wert der Opacity-Eigenschaft des entsprechenden UIElements.
Beispiel für Offsetanimation
Falsch
<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);
Die ElementCompositionPreview.SetElementChildVisual-Methode
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 ".
Anleitungen
Animation neu positionieren
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.
Implementierungsübersicht
- Abrufen des Handzettels für das Zielelement
- Erstellen einer ImplicitAnimationCollection , die Änderungen in der Offset-Eigenschaft automatisch animiert
- Zuordnen der ImplicitAnimationCollection zum zugrunde stehenden visuellen Element
<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.
Implementierungsübersicht
- Abrufen des Handzettels für das Hostelement
- Erstellen eines Windows.UI.Composition DropShadow
- Konfigurieren des DropShadows, um seine Form aus dem Zielelement über eine Maske abzurufen
- DropShadow ist standardmäßig rechteckig, daher ist dies nicht erforderlich, wenn das Ziel rechteckig ist.
- Anfügen eines Schattens an ein neues SpriteVisual-Element und Festlegen des SpriteVisual als untergeordnetes Element des Hostelements
- Binden der Größe des SpriteVisual-Elements an die Größe des Hosts mithilfe einer 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);
}
In den folgenden beiden Auflistungen werden die C++/WinRT - und C++/CX-Entsprechungen des vorherigen C#-Codes mit derselben XAML-Struktur angezeigt.
#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);
}
Milchglas
Erstellen Sie einen Effekt, der Hintergrundinhalte weichzeichnen und tönt. Beachten Sie, dass Entwickler das Win2D NuGet-Paket installieren müssen, um Effekte zu verwenden. Installationsanweisungen finden Sie auf der Win2D-Homepage .
Implementierungsübersicht
- Abrufen von Handzetteln für das Hostelement
- Erstellen einer Weichzeichnereffektstruktur mit Win2D und CompositionEffectSourceParameter
- Erstellen eines CompositionEffectBrush basierend auf der Effektstruktur
- Festlegen der Eingabe von CompositionEffectBrush auf einen CompositionBackdropBrush, wodurch ein Effekt auf den Inhalt hinter einem SpriteVisual angewendet werden kann
- 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.
- Binden der Größe des SpriteVisual-Elements an die Größe 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);
}
Weitere Ressourcen
- Übersicht über die visuelle Ebene
- ElementCompositionPreview-Klasse
- Erweiterte UI- und Kompositionsbeispiele in WindowsCompositionSamples GitHub
- BasicXamlInterop-Beispiel
- ParallaxingListItems-Beispiel