Menggunakan Lapisan Visual dengan XAML

Sebagian besar aplikasi yang menggunakan kemampuan Lapisan Visual akan menggunakan XAML untuk menentukan konten UI utama. Dalam Windows 10 Anniversary Update, ada fitur baru dalam kerangka kerja XAML dan Visual Layer yang memudahkan untuk menggabungkan kedua teknologi ini untuk menciptakan pengalaman pengguna yang menakjubkan. Fungsionalitas interop XAML dan Visual Layer dapat digunakan untuk membuat animasi dan efek tingkat lanjut yang tidak tersedia menggunakan API XAML saja. Ini termasuk:

  • Efek sikat seperti kaca buram dan beku
  • Efek pencahayaan dinamis
  • Menggulir animasi dan parallax yang didorong
  • Animasi tata letak otomatis
  • Bayangan drop sempurna piksel

Efek dan animasi ini dapat diterapkan ke konten XAML yang ada, sehingga Anda tidak perlu merestrukturisasi aplikasi XAML Anda secara dramatis untuk memanfaatkan fungsionalitas baru. Animasi tata letak, bayangan, dan efek kabur tercakup dalam bagian Resep di bawah ini. Untuk contoh kode yang mengimplementasikan parallax, lihat sampel ParallaxingListItems. Repositori WindowsCompositionSamples juga memiliki beberapa sampel lain untuk mengimplementasikan animasi, bayangan, dan efek.

Kelas XamlCompositionBrushBase

XamlCompositionBrush menyediakan kelas dasar untuk kuas XAML yang melukis area dengan CompositionBrush. Ini dapat digunakan untuk dengan mudah menerapkan efek komposisi seperti blur atau frosted glass ke elemen UI XAML.

Lihat bagian Sikat untuk informasi selengkapnya tentang menggunakan kuas dengan UI XAML.

Untuk contoh kode, lihat halaman referensi untuk XamlCompositionBrushBase.

Kelas XamlLight

XamlLight menyediakan kelas dasar untuk efek pencahayaan XAML yang secara dinamis menyalakan area dengan CompositionLight.

Lihat bagian Pencahayaan untuk informasi selengkapnya tentang menggunakan lampu, termasuk elemen antarmuka pengguna XAML pencahayaan.

Untuk contoh kode, lihat halaman referensi untuk XamlLight.

Kelas ElementCompositionPreview

ElementCompositionPreview adalah kelas statis yang menyediakan fungsionalitas interop XAML dan Visual Layer. Untuk gambaran umum Visual Layer dan fungsionalitasnya, lihat Visual Layer. Kelas ElementCompositionPreview menyediakan metode berikut:

Keterangan tentang ElementCompositionPreview.GetElementVisual

ElementCompositionPreview.GetElementVisual mengembalikan Visual "handout" yang digunakan untuk merender UIElement yang diberikan. Properti seperti Visual.Opacity, Visual.Offset, dan Visual.Size diatur oleh kerangka kerja XAML berdasarkan status UIElement. Ini memungkinkan teknik seperti animasi reposisi implisit (lihat Resep).

Perhatikan bahwa karena Offset dan Ukuran ditetapkan sebagai hasil tata letak kerangka kerja XAML, pengembang harus berhati-hati saat memodifikasi atau menganimasikan properti ini. Pengembang hanya boleh memodifikasi atau menganimasikan Offset ketika sudut kiri atas elemen memiliki posisi yang sama dengan induknya dalam tata letak. Ukuran umumnya tidak boleh dimodifikasi, tetapi mengakses properti mungkin berguna. Misalnya, sampel Drop Shadow dan Frosted Glass di bawah ini menggunakan Ukuran Visual makalah sebagai input ke animasi.

Sebagai peringatan tambahan, properti visual makalah yang diperbarui tidak akan tercermin dalam UIElement yang sesuai. Jadi misalnya, mengatur UIElement.Opacity ke 0,5 akan mengatur Opacity Visual makalah yang sesuai ke 0,5. Namun, mengatur Opacity Visual makalah menjadi 0,5 akan menyebabkan konten muncul pada tingkat keburaman 50%, tetapi tidak akan mengubah nilai properti Opacity UIElement yang sesuai.

Contoh animasi Offset

Salah

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

Benar

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

Metode ElementCompositionPreview.SetElementChildVisual

ElementCompositionPreview.SetElementChildVisual memungkinkan pengembang untuk menyediakan Visual "handin" yang akan muncul sebagai bagian dari Visual Tree elemen. Hal ini memungkinkan pengembang untuk membuat "Pulau Komposisi" di mana konten berbasis Visual dapat muncul di dalam antarmuka pengguna XAML. Pengembang harus konservatif tentang menggunakan teknik ini karena konten berbasis Visual tidak akan memiliki aksesibilitas dan jaminan pengalaman pengguna yang sama dari konten XAML. Oleh karena itu, umumnya disarankan agar teknik ini hanya digunakan jika perlu untuk mengimplementasikan efek kustom seperti yang ditemukan di bagian Resep di bawah ini.

Metode GetAlphaMask

Gambar, TextBlock, dan Shape masing-masing mengimplementasikan metode yang disebut GetAlphaMask yang mengembalikan CompositionBrush yang mewakili gambar skala abu-abu dengan bentuk elemen . KomposisiBrush ini dapat berfungsi sebagai input untuk Komposisi DropShadow, sehingga bayangan dapat mencerminkan bentuk elemen alih-alih persegi panjang. Ini memungkinkan bayangan piksel sempurna berbasis kontur untuk teks, gambar dengan alfa, dan bentuk. Lihat Drop Shadow di bawah ini untuk contoh API ini.

Resep

Memposisikan ulang animasi

Menggunakan Animasi Implisit Komposisi, pengembang dapat secara otomatis menganimasikan perubahan dalam tata letak elemen relatif terhadap induknya. Misalnya, jika Anda mengubah Margin tombol di bawah ini, itu akan secara otomatis menganimasikan ke posisi tata letak barunya.

Gambaran umum implementasi

  1. Mendapatkan Visual handout untuk elemen target
  2. Membuat ImplicitAnimationCollection yang secara otomatis menganimasikan perubahan di properti Offset
  3. Kaitkan ImplicitAnimationCollection dengan Visual yang mendukung
<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;
}

Jatuhkan bayangan

Terapkan bayangan drop sempurna piksel ke UIElement, misalnya Elips yang berisi gambar. Karena bayangan memerlukan SpriteVisual yang dibuat oleh aplikasi, kita perlu membuat elemen "host" yang akan berisi SpriteVisual menggunakan ElementCompositionPreview.SetElementChildVisual.

Gambaran umum implementasi

  1. Mendapatkan Visual handout untuk elemen host
  2. Membuat DropShadow Komposisi Windows.UI.
  3. Mengonfigurasi DropShadow untuk mendapatkan bentuknya dari elemen target melalui masker
    • DropShadow persegi panjang secara default, jadi ini tidak diperlukan jika target persegi panjang
  4. Lampirkan bayangan ke SpriteVisual baru, dan atur SpriteVisual sebagai anak dari elemen host
  5. Ukuran ikatan SpriteVisual ke ukuran host menggunakan 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);
}

Dua daftar berikut menunjukkan C ++/WinRT dan C++/CX yang setara dengan kode C# sebelumnya menggunakan struktur XAML yang sama.

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

Kaca beku

Buat efek yang mengaburkan dan menyaring konten latar belakang. Perhatikan bahwa pengembang perlu menginstal paket Win2D NuGet untuk menggunakan efek. Lihat beranda Win2D untuk instruksi penginstalan.

Gambaran umum implementasi

  1. Mendapatkan Visual handout untuk elemen host
  2. Membuat pohon efek kabur menggunakan Win2D dan KomposisiEffectSourceParameter
  3. Membuat KomposisiEffectBrush berdasarkan pohon efek
  4. Atur input KomposisiEffectBrush ke KomposisiBackdropBrush, yang memungkinkan efek untuk diterapkan pada konten di belakang SpriteVisual
  5. Atur KomposisiEffectBrush sebagai konten SpriteVisual baru, dan atur SpriteVisual sebagai anak dari elemen host. Anda dapat menggunakan XamlCompositionBrushBase alternatif.
  6. Ukuran ikatan SpriteVisual ke ukuran host menggunakan 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);
}

Sumber Daya Tambahan