Udostępnij za pośrednictwem


Używanie warstwy wizualnej z językiem XAML WinUI

Większość aplikacji WinUI i Zestawu SDK aplikacji systemu Windows korzystających z funkcji warstwy wizualnej będzie używać języka XAML do definiowania głównej zawartości interfejsu użytkownika. Platforma WinUI udostępnia funkcje w strukturze XAML i warstwie wizualnej, które ułatwiają łączenie tych dwóch technologii w celu tworzenia wspaniałych środowisk użytkownika. Funkcje międzyoperacyjności XAML i Visual Layer mogą służyć do tworzenia zaawansowanych animacji i efektów niedostępnych za pomocą samych interfejsów API XAML. Obejmuje to:

  • Efekty szczotki, takie jak rozmycie i matowe szkło
  • Dynamiczne efekty oświetlenia
  • Animacje sterowane przewijaniem i efekt paralaksy
  • Automatyczne animacje układu
  • Doskonałe cienie w pikselach

Te efekty i animacje można zastosować do istniejącej zawartości XAML, więc nie trzeba znacząco zmieniać struktury aplikacji WinUI, aby korzystać z funkcji. Animacje układu, cienie i efekty rozmycia zostały omówione w poniższej sekcji Przepisy. Można znaleźć przykład implementacji efektu parallax w przykładzie ParallaxingListItems. Repozytorium WindowsCompositionSamples zawiera również kilka innych przykładów do implementowania animacji, cieni i efektów.

Klasa XamlCompositionBrushBase

Microsoft.UI.Xaml.Media.XamlCompositionBrushBase udostępnia klasę bazową pędzli XAML, które malują obszar za pomocą pędzla CompositionBrush. Może to służyć do łatwego stosowania efektów kompozycji, takich jak rozmycie lub matowe szkło do elementów interfejsu użytkownika XAML.

Aby uzyskać więcej informacji na temat używania pędzli z interfejsem użytkownika XAML, zobacz sekcję Szczotki .

Przykłady kodu można znaleźć na stronie referencyjnej elementu XamlCompositionBrushBase.

Klasa XamlLight

Microsoft.UI.Xaml.Media.XamlLight udostępnia klasę bazową efektów oświetleniowych XAML, które dynamicznie oświetlają obszar przy użyciu CompositionLight.

Zobacz sekcję Oświetlenie , aby uzyskać więcej informacji na temat używania świateł, w tym oświetlenia elementów interfejsu użytkownika XAML.

Przykłady kodu można znaleźć na stronie referencyjnej elementu XamlLight.

Praca z WinUI XAML

ElementCompositionPreview to klasa statyczna, która zapewnia funkcje międzyoperacjonatyczne XAML i Visual Layer. Aby zapoznać się z omówieniem warstwy wizualnej i jej funkcjonalności, zobacz Visual Layer. Klasa ElementCompositionPreview udostępnia następujące metody międzyoperacji WinUI:

  • GetElementVisual: pobierz wizualizację domyślną, używaną do renderowania tego elementu
  • SetElementChildVisual: ustawia "handin" Visual jako ostatni podrzędny element drzewa wizualnego tego elementu. Ta wizualizacja będzie rysowana nad pozostałymi elementami.
  • GetElementChildVisual: Pobierz zestaw obiektów wizualnych przy użyciu SetElementChildVisual
  • GetScrollViewerManipulationPropertySet: pobierz obiekt, który może służyć do tworzenia animacji 60fps na podstawie przesunięcia przewijania w programie ScrollViewer

GetElementVisual

ElementCompositionPreview.GetElementVisual zwraca wizualizację "handout", która jest używana do renderowania danego elementu UIElement. Właściwości, takie jak Visual.Opacity, Visual.Offset i Visual.Size , są ustawiane przez strukturę XAML na podstawie stanu elementu UIElement. Umożliwia to techniki, takie jak niejawne animacje zmieniania położenia (zobacz Przepisy).

Należy pamiętać, że ponieważ przesunięcie i rozmiar są ustawiane w wyniku układu struktury XAML, deweloperzy powinni zachować ostrożność podczas modyfikowania lub animowania tych właściwości. Deweloperzy powinni modyfikować lub animować Offset tylko wtedy, gdy lewy górny róg elementu ma tę samą pozycję w układzie co róg lewego górnego elementu nadrzędnego. Rozmiar nie powinien być zwykle modyfikowany, ale uzyskiwanie dostępu do właściwości może być przydatne. Na przykład poniższe próbki Drop Shadow i Frosted Glass używają opcji Rozmiar wizualizacji informacyjnej jako danych wejściowych do animacji.

W ramach dodatkowego zastrzeżenia zaktualizowane właściwości wizualizacji informacyjnej nie zostaną odzwierciedlone w odpowiednim elemecie UIElement. Na przykład ustawienie UIElement.Opacity na 0,5 spowoduje ustawienie odpowiedniego nieprzezroczystości elementu wizualnego na 0,5. Jednakże ustawienie przezroczystości wizualizacji na 0,5 spowoduje, że jej zawartość będzie wyświetlana z 50% przezroczystości, ale nie zmieni wartości właściwości Przezroczystości odpowiadającego elementu UIElement.

Przykład animacji przesunięcia

Błędny

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

Poprawny

<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

ElementCompositionPreview.SetElementChildVisual umożliwia deweloperowi podanie wizualizacji "handin", która będzie wyświetlana jako część drzewa wizualnego elementu. Dzięki temu deweloperzy mogą utworzyć "Wyspę kompozycji", na której zawartość oparta na wizualizacji może pojawiać się w interfejsie użytkownika XAML. Deweloperzy powinni być ostrożni w korzystaniu z tej techniki, ponieważ zawartość oparta na obrazie nie będzie mieć takich samych ułatwień dostępu i gwarancji doświadczenia użytkownika jak zawartość XAML. W związku z tym zaleca się stosowanie tej techniki tylko wtedy, gdy jest to konieczne do zaimplementowania efektów niestandardowych, takich jak te znajdujące się w sekcji Przepisy poniżej.

Metody GetAlphaMask

Obraz, TextBlock i Shape każdy implementuje metodę o nazwie GetAlphaMask , która zwraca element CompositionBrush reprezentujący obraz skali szarości z kształtem elementu. Ten CompositionBrush może być użyty jako dane wejściowe dla kompozycji DropShadow, dzięki czemu cień może odzwierciedlać kształt elementu, a nie prostokąta. Umożliwia to idealnie dopasowane cienie na podstawie konturu dla tekstu, obrazów z kanałem alfa i kształtów. Zobacz Drop Shadow poniżej, aby zapoznać się z przykładem tego interfejsu API.

Przepisy

Zmienia położenie animacji

Korzystając z niejawnych animacji kompozycji, deweloper może automatycznie animować zmiany w układzie elementu względem jego elementu nadrzędnego. Jeśli na przykład zmienisz margines poniższego przycisku, zostanie on automatycznie animowany do nowej pozycji w układzie.

Omówienie implementacji

  1. Pobierz materiał Wizualny dla elementu docelowego
  2. Tworzenie obiektu ImplicitAnimationCollection, który automatycznie animuje zmiany we właściwości Offset
  3. Kojarzenie elementu ImplicitAnimationCollection z wizualizacją zapasową
<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;
}

Cień

Zastosuj cień spadający, idealny w pikselach do UIElementu, na przykład Elipsy zawierającej obraz. Ponieważ cień wymaga SpriteVisual utworzonego przez aplikację, musimy utworzyć element „host”, który będzie zawierać SpriteVisual przy użyciu ElementCompositionPreview.SetElementChildVisual.

Omówienie implementacji

  1. Pobierz wizualny materiał dla hosta elementu
  2. Utwórz Microsoft.UI.Composition DropShadow
  3. Skonfiguruj DropShadow, aby uzyskać jego kształt z elementu docelowego za pomocą maski
    • DropShadow jest domyślnie prostokątny, więc nie jest to konieczne, jeśli obiekt docelowy jest prostokątny
  4. Dołącz cień do nowego elementu SpriteVisual i ustaw element SpriteVisual jako element podrzędny elementu hosta
  5. Powiąż rozmiar SpriteVisual z rozmiarem hosta, używając 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);
}

Na poniższej liście przedstawiono odpowiednik kodu C++/WinRT z poprzedniego kodu języka C# przy użyciu tej samej struktury XAML.

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

Szkło matowe

Utwórz efekt, który rozmywa i barwi zawartość tła. Należy pamiętać, że deweloperzy muszą zainstalować pakiet NuGet Win2D, aby używać efektów. Aby uzyskać instrukcje instalacji, zobacz stronę główną Win2D .

Omówienie implementacji

  1. Pobierz wizualizację dla elementu hosta
  2. Tworzenie drzewa efektu rozmycia przy użyciu Win2D i CompositionEffectSourceParameter
  3. Tworzenie elementu CompositionEffectBrush na podstawie drzewa efektów
  4. Ustaw wejście CompositionEffectBrush na CompositionBackdropBrush, co pozwala na zastosowanie efektu do zawartości za SpriteVisual
  5. Ustaw element CompositionEffectBrush jako zawartość nowego elementu SpriteVisual, a następnie ustaw element SpriteVisual jako element podrzędny elementu hosta. Alternatywnie można użyć klasy XamlCompositionBrushBase.
  6. Powiąż rozmiar komponentu SpriteVisual z rozmiarem hosta, używając WyrażeniaAnimacji
<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);
}

Dodatkowe zasoby