Sdílet prostřednictvím


Použití vizuální vrstvy s jazykem WinUI XAML

Většina aplikací WinUI a Windows App SDK, které využívají funkce vizuální vrstvy, použije XAML k definování hlavního obsahu uživatelského rozhraní. WinUI poskytuje funkce v rozhraní XAML a vizuální vrstvě, které usnadňují kombinování těchto dvou technologií za účelem vytvoření poutavých uživatelských prostředí. Funkce spolupráce XAML a vizuální vrstvy je možné použít k vytváření pokročilých animací a efektů, které nejsou k dispozici pomocí samotných rozhraní XAML API. Sem patří:

  • Efekty štětce, jako je rozostření a omrzlé sklo
  • Dynamické efekty osvětlení
  • Rulované animace a paralaxa
  • Automatické animace rozložení
  • Dokonalé stíny v pixelech

Tyto efekty a animace je možné použít u existujícího obsahu XAML, takže nemusíte výrazně restrukturalizovat aplikaci WinUI, abyste mohli využívat výhod funkcí. Animace rozložení, stíny a rozostření jsou popsané v části Recepty níže. Ukázku kódu implementující parallax najdete v ukázce ParallaxingListItems. Úložiště WindowsCompositionSamples má také několik dalších ukázek pro implementaci animací, stínů a efektů.

Třída „XamlCompositionBrushBase“

Microsoft.UI.Xaml.Media.XamlCompositionBrushBase poskytuje základní třídu pro štětce XAML, které malují oblast pomocí CompositionBrush. To se dá použít k snadnému použití kompozičních efektů, jako je rozostření nebo omrzlé sklo, na prvky uživatelského rozhraní XAML.

Další informace o používání štětců s uživatelským rozhraním XAML najdete v části Štětce .

Příklady kódu najdete na referenční stránce xamlCompositionBrushBase.

Třída XamlLight

Microsoft.UI.Xaml.Media.XamlLight poskytuje základní třídu pro světelné efekty XAML, které dynamicky osvětlují oblast pomocí CompositionLight.

Další informace o používání světel, včetně prvků uživatelského rozhraní XAML, najdete v části Osvětlení .

Příklady kódu najdete na referenční stránce XamlLight.

Práce s WinUI XAML

ElementCompositionPreview je statická třída, která poskytuje funkce spolupráce XAML a vizuální vrstvy. Přehled vizuální vrstvy a její funkce najdete v tématu Vizuální vrstva. ElementCompositionPreview třída poskytuje následující winUI interop metody:

GetElementVisual

ElementCompositionPreview.GetElementVisual vrátí "podpůrný" Visual použitý k vykreslení daného prvku UIElement. Vlastnosti, jako jsou Visual.Opacity, Visual.Offset a Visual.Size , jsou nastaveny architekturou XAML na základě stavu UIElement. To umožňuje techniky, jako je implicitní změna umístění animací (viz Recepty).

Všimněte si, že vzhledem k tomu, že jsou v důsledku rozložení architektury XAML nastaveny posun a velikost , měli by vývojáři při úpravách nebo animaci těchto vlastností dávat pozor. Vývojáři by měli změnit nebo animovat posun pouze tehdy, když je levý horní roh prvku ve stejné pozici jako v případě jeho nadřazeného prvku v rozložení. Velikost by se obecně neměla měnit, ale přístup k této vlastnosti může být užitečný. Například ukázky Drop Shadow a Frosted Glass níže používají velikost vizuálu pracovního listu jako vstup do animace.

Další upozornění: aktualizované vlastnosti vizuálu podkladového materiálu se neprojeví v odpovídajícím prvku "UIElement". Například nastavení uiElement.Opacity na hodnotu 0.5 nastaví odpovídající neprůhlednost vizuálu podkladů na hodnotu 0.5. Nastavení vlastnosti Opacity vizuálu prezentace na hodnotu 0,5 způsobí, že se obsah zobrazí s 50% průhledností, ale nezmění hodnotu vlastnosti Opacity odpovídajícího prvku UIElement.

Příklad offsetové animace

Nesprávný

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

Opravit

<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žňuje vývojáři zadat vizuál "handin", který se zobrazí jako součást vizuálního stromu elementu. Díky tomu můžou vývojáři vytvořit "Ostrov složení", kde se vizuální obsah může objevit v uživatelském rozhraní XAML. Vývojáři by měli být konzervativní na používání této techniky, protože vizuální obsah nebude mít stejné záruky přístupnosti a uživatelského prostředí obsahu XAML. Proto se obecně doporučuje, aby se tato technika používala pouze v případě, že je potřeba implementovat vlastní efekty, jako jsou ty, které najdete v části Recepty níže.

Metody GetAlphaMask

Image, TextBlock a Shape každý implementuje metodu s názvem GetAlphaMask , která vrací CompositionBrush představující obrázek ve stupních šedé s tvarem prvku. Tento Objekt CompositionBrush může sloužit jako vstup pro Composition DropShadow, takže stín může odrážet tvar prvku místo obdélníku. To umožňuje dokonalé stíny založené na obrysu pro text, obrázky s alfou a obrazce. Příklad tohoto rozhraní API najdete níže v části Odrazový stín.

Recepty

Změna umístění animace

Pomocí implicitních animací kompozice může vývojář automaticky animovat změny v rozložení elementu vzhledem k nadřazenému prvku. Pokud například změníte okraj tlačítka níže, automaticky se animuje do nové pozice rozložení.

Přehled implementace

  1. Získejte materiál Visual pro cílový element
  2. Vytvoření ImplicitAnimationCollection , která automaticky animuje změny v offset vlastnosti
  3. Propojte ImplicitAnimationCollection s podpůrným 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;
}

Vržený stín

Na UIElement aplikujte stín s dokonalou přesností pixelů, například na elipsu obsahující obrázek. Vzhledem k tomu, stín vyžaduje SpriteVisual vytvořený aplikací, musíme vytvořit "host" element, který bude obsahovat SpriteVisual pomocí ElementCompositionPreview.SetElementChildVisual.

Přehled implementace

  1. Získejte vizuál pro hostitelský prvek
  2. Vytvořte Microsoft.UI.Composition DropShadow
  3. Nakonfigurujte DropShadow tak, aby získal tvar z cílového prvku prostřednictvím masky.
    • DropShadow je ve výchozím nastavení obdélníkový, takže to není nutné, pokud je cíl obdélníkový.
  4. Připojení stínu k novému objektu SpriteVisual a nastavení SpriteVisual jako podřízeného prvku hostitele
  5. Vytvoření vazby velikosti SpriteVisual na velikost hostitele pomocí 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);
}

Následující výpis ukazuje ekvivalent C++/WinRT předchozího kódu jazyka C# se stejnou strukturou 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);
}

Zamrzlé sklo

Vytvořte efekt, který rozostří a zabarví obsah pozadí. Všimněte si, že vývojáři musí nainstalovat balíček NuGet Win2D, aby mohli používat efekty. Pokyny k instalaci najdete na domovské stránce Win2D .

Přehled implementace

  1. Získejte podklad Visual pro prvek hostitele
  2. Vytvoření stromu rozostřených efektů pomocí Win2D a CompositionEffectSourceParameter
  3. Vytvoření objektu CompositionEffectBrush na základě stromu efektu
  4. Nastavte vstup CompositionEffectBrush na CompositionBackdropBrush, který umožňuje použití efektu na obsah za SpriteVisual
  5. Nastavte CompositionEffectBrush jako obsah nového SpriteVisual a nastavte SpriteVisual jako podřízený prvek hostitele. Alternativně můžete použít XamlCompositionBrushBase.
  6. Vytvoření vazby velikosti SpriteVisual na velikost hostitele pomocí 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);
}

Další zdroje