Использование визуального уровня с помощью XAMLUsing the Visual Layer with XAML

Большинство приложений, задействующих возможности визуального уровня, будут использовать XAML для определения содержимого основного пользовательского интерфейса.Most apps that consume Visual Layer capabilities will use XAML to define the main UI content. В юбилейном обновлении Windows 10 предусмотрены новые возможности платформы XAML и визуального уровня, которые упрощают объединение этих двух технологий для создания потрясающих элементов взаимодействия с пользователем.In the Windows 10 Anniversary Update, there are new features in the XAML framework and the Visual Layer that make it easier to combine these two technologies to create stunning user experiences. Функциональность взаимодействия XAML и визуального уровня можно использовать для создания сложных анимаций и эффектов, недоступных при использовании только интерфейсов API XAML.XAML and Visual Layer interop functionality can be used to create advanced animations and effects not available using XAML APIs alone. Сюда входят следующие возможности.This includes:

  • Эффекты кисти, например размытие и матированное стеклоBrush effects like blur and frosted glass
  • Эффекты динамического освещенияDynamic lighting effects
  • Анимации и параллакс, управляемые прокруткойScroll driven animations and parallax
  • Автоматические анимации макетаAutomatic layout animations
  • Точные до пикселя тениPixel-perfect drop shadows

Эти эффекты и анимации можно применять к существующему содержимому XAML, поэтому вам не придется кардинально менять структуру вашего приложения на XAML, чтобы использовать эти новые функции.These effects and animations can be applied to existing XAML content, so you don't have to dramatically restructure your XAML app to take advantage of the new functionality. Анимации макета, тени и эффекты размытия описываются в разделе рецептов ниже.Layout animations, shadows, and blur effects are covered in the Recipes section below. Пример кода с реализацией параллакса см. в разделе Пример ParallaxingListItems.For a code sample implementing parallax, see the ParallaxingListItems sample. В репозитории WindowsUIDevLabs также есть ряд других примеров реализации анимаций, теней и эффектов.The WindowsUIDevLabs repository also has several other samples for implementing animations, shadows and effects.

Класс XamlCompositionBrushBaseThe XamlCompositionBrushBase class

XamlCompositionBrush представляет собой базовый класс для кистей XAML, которые закрашивают область с использованием CompositionBrush.XamlCompositionBrush provides a base class for XAML brushes that paint an area with a CompositionBrush. С его помощью можно легко применять эффекты композиции, такие как размытие или матовое стекло, к элементам пользовательского интерфейса на XAML.This can be used to easily apply composition effects like blur or frosted glass to XAML UI elements.

Дополнительные сведения об использовании кистей с пользовательским интерфейсом на XAML см. в разделе Кисти.See the Brushes section for more info on using brushes with XAML UI.

Примеры кода см. на странице со справочной документацией по XamlCompositionBrushBase.For code examples, see the reference page for XamlCompositionBrushBase.

Класс XamlLightThe XamlLight class

XamlLight представляет собой базовый класс для эффектов освещения XAML, которые динамически освещают область с использованием CompositionLight.XamlLight provides a base class for XAML lighting effects that dynamically light an area with a CompositionLight.

Дополнительную информацию об использовании источников света, включая элементы пользовательского интерфейса на XAML, см. в разделе Освещение.See the Lighting section for more info on using lights, including lighting XAML UI elements.

Примеры кода см. на странице со справочной документацией по XamlLight.For code examples, see the reference page for XamlLight.

Класс ElementCompositionPreviewThe ElementCompositionPreview class

Елементкомпоситионпревиев — это статический класс, предоставляющий функциональные возможности взаимодействия XAML и визуального слоя.ElementCompositionPreview is a static class that provides XAML and Visual Layer interop functionality. Обзор визуального уровня и его функций см. в разделе Визуальный уровень.For an overview of the Visual Layer and its functionality, see Visual Layer. Класс ElementCompositionPreview предоставляет следующие методы.The ElementCompositionPreview class provides the following methods:

  • Жетелементвисуал: получение визуального элемента "раздаточные материалы", который используется для отрисовки этих элементовGetElementVisual: Get a "handout" Visual that is used to render this element
  • Сетелементчилдвисуал: задает визуальный элемент "руки" в качестве последнего дочернего элемента визуального дерева этого элемента.SetElementChildVisual: Sets a "handin" Visual as the last child of this element’s visual tree. Этот объект Visual отрисовывается поверх остальных элементов.This Visual will draw on top of the rest of the element.
  • Жетелементчилдвисуал: получение набора визуальных элементов с помощью сетелементчилдвисуалGetElementChildVisual: Retrieve the Visual set using SetElementChildVisual
  • Жетскроллвиеверманипулатионпропертисет: получение объекта, который можно использовать для создания анимации 60fps на основе смещения прокрутки в ScrollViewerGetScrollViewerManipulationPropertySet: Get an object that can be used to create 60fps animations based on scroll offset in a ScrollViewer

Примечания относительно ElementCompositionPreview.GetElementVisualRemarks on ElementCompositionPreview.GetElementVisual

ElementCompositionPreview.GetElementVisual возвращает "выдаваемый" объект Visual, используемый для отрисовки данного UIElement.ElementCompositionPreview.GetElementVisual returns a “handout” Visual that is used to render the given UIElement. Такие свойства, как Visual.Opacity, Visual.Offset и Visual.Size, устанавливаются платформой XAML на основании состояния UIElement.Properties such as Visual.Opacity, Visual.Offset, and Visual.Size are set by the XAML framework based on the state of the UIElement. Это позволяет использовать такие методы, как неявные анимации изменения положения (см. Рецепты).This enables techniques such as implicit reposition animations (see Recipes).

Обратите внимание, что, поскольку свойства Offset и Size задаются в соответствии с макетом платформы на XAML, разработчикам следует осторожно подходить к изменению и анимации этих свойств.Note that since Offset and Size are set as the result of XAML framework layout, developers should be careful when modifying or animating these properties. Разработчикам следует изменять и анимировать Offset, только когда верхний левый угол элемента совпадает с верхним левым углом его родительского элемента в макете.Developers should only modify or animate Offset when the element’s top-left corner has the same position as that of its parent in layout. Размер обычно не следует менять, но доступ к этому свойству может быть полезен.Size should generally not be modified, but accessing the property may be useful. Например, в приведенных ниже примерах с отбрасыванием тени и матированным стеклом свойство Size выданного объекта Visual используется в качестве входных данных для анимации.For example, the Drop Shadow and Frosted Glass samples below use Size of a handout Visual as input to an animation.

Также следует помнить, что обновленные свойства выданного объекта Visual не будут отражаться в соответствующем UIElement.As an additional caveat, updated properties of the handout Visual will not be reflected in the corresponding UIElement. Так, например, установка для UIElement.Opacity значения 0,5 задаст прозрачности соответствующего выданного объекта Visual значение 0,5.So for example, setting UIElement.Opacity to 0.5 will set the corresponding handout Visual’s Opacity to 0.5. Однако установка свойству Opacity выданного объекта Visual значения 0,5 приведет к тому, что содержимое будет отображаться с прозрачностью 50%, но это не изменит значение свойства Opacity соответствующего UIElement.However, setting the handout Visual’s Opacity to 0.5 will cause the content to appear at 50% opacity, but will not change the value of the corresponding UIElement’s Opacity property.

Пример анимации OffsetExample of Offset animation

НеверноIncorrect

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

ВерноCorrect

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

Метод ElementCompositionPreview.SetElementChildVisualThe ElementCompositionPreview.SetElementChildVisual method

ElementCompositionPreview.SetElementChildVisual позволяет разработчику предоставить "возвращаемый" объект Visual, который будет отображаться как часть визуального дерева элемента.ElementCompositionPreview.SetElementChildVisual allows the developer to supply a “handin” Visual that will appear as part of an element’s Visual Tree. Это позволяет разработчикам создавать "Остров композиции", где содержимое на основе объекта Visual может размещаться в пользовательском интерфейсе на XAML.This allows developers to create a “Composition Island” where Visual-based content can appear inside a XAML UI. Разработчикам следует осторожно использовать этот подход, поскольку содержимое на основе объекта Visual не будет обладать теми же гарантиями по специальным возможностям и взаимодействию с пользователем, как содержимое на XAML.Developers should be conservative about using this technique because Visual-based content will not have the same accessibility and user experience guarantees of XAML content. Соответственно, обычно рекомендуется использовать этот метод, только если это необходимо для реализации пользовательских эффектов, подобных приведенным ниже в разделе рецептов.Therefore, it is generally recommended that this technique only be used when necessary to implement custom effects such as those found in the Recipes section below.

Методы GetAlphaMaskGetAlphaMask methods

Image, TextBlockи Shape реализуют метод с именем жеталфамаск , который возвращает компоситионбруш , представляющий изображение в градациях серого, с формой элемента.Image, TextBlock, and Shape each implement a method called GetAlphaMask that returns a CompositionBrush representing a grayscale image with the shape of the element. Этот объект CompositionBrush может служить входными данными для DropShadow композиции, чтобы тень соответствовала форме элемента и не была просто прямоугольной.This CompositionBrush can serve as an input for a Composition DropShadow, so the shadow can reflect the shape of the element instead of a rectangle. Это позволяет использовать точные до пикселя основанные на контурах тени для текста, изображений с альфа-каналом и различных фигур.This enables pixel perfect, contour-based shadows for text, images with alpha, and shapes. См. раздел Отбрасывание тени ниже для ознакомления с примером этого API.See Drop Shadow below for an example of this API.

РецептыRecipes

Анимация перемещенияReposition animation

Используя неявные анимации композиции, разработчик может автоматически анимировать изменения в макете элемента по отношению к его родительскому элементу.Using Composition Implicit Animations, a developer can automatically animate changes in an element’s layout relative to its parent. Например, если изменить свойство Margin приведенной ниже кнопки, она автоматически анимированным образом переместится на свое новое место в макете.For example, if you change the Margin of the button below, it will automatically animate to its new layout position.

Обзор реализацииImplementation overview

  1. Получение выдаваемого объекта Visual для целевого элементаGet the handout Visual for the target element
  2. Создание ImplicitAnimationCollection, что автоматически анимирует изменения в свойстве OffsetCreate an ImplicitAnimationCollection that automatically animates changes in the Offset property
  3. Связывание ImplicitAnimationCollection с поддерживающим объектом VisualAssociate the ImplicitAnimationCollection with the backing 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;
}

Отбрасывание тениDrop shadow

Добавление точной до пикселя тени для UIElement, например Ellipse с картинкой.Apply a pixel-perfect drop shadow to a UIElement, for example an Ellipse containing a picture. Поскольку тень требует создания SpriteVisual приложением, необходимо создать "принимающий" элемент, который будет содержать SpriteVisual с помощью ElementCompositionPreview.SetElementChildVisual.Since the shadow requires a SpriteVisual created by the app, we need to create a “host” element which will contain the SpriteVisual using ElementCompositionPreview.SetElementChildVisual.

Обзор реализацииImplementation overview

  1. Получение выдаваемого объекта Visual для принимающего элементаGet the handout Visual for the host element
  2. Создание DropShadow из Windows.UI.CompositionCreate a Windows.UI.Composition DropShadow
  3. Настройка DropShadow для получения формы тени из целевого элемента через маскуConfigure the DropShadow to get its shape from the target element via a mask
    • DropShadow по умолчанию имеет прямоугольную форму, так что этот этап не требуется, если целевой объект прямоугольныйDropShadow is rectangular by default, so this is not necessary if the target is rectangular
  4. Прикрепление тени к новому объекту SpriteVisual и назначение SpriteVisual дочерним элементом принимающего элементаAttach shadow to a new SpriteVisual, and set the SpriteVisual as the child of the host element
  5. Привязка размера SpriteVisual к размеру принимающего элемента с помощью ExpressionAnimationBind size of the SpriteVisual to the size of the host using an 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);
}

В следующих двух примерах представлены эквиваленты кода на C++/WinRT и C++/CX предыдущего кода C#, в которых используется одинаковая структура XAML.The following two listings show the C++/WinRT and C++/CX equivalents of the previous C# code using the same XAML structure.

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

Матированное стеклоFrosted glass

Создание эффекта, размывающего и придающего оттенок расположенному за ним содержимому.Create an effect that blurs and tints background content. Обратите внимание, что для использования эффектов разработчики должны установить пакет Win2D NuGet.Note that developers need to install the Win2D NuGet package to use effects. Инструкции по установке см. на Домашней странице Win2D.See the Win2D homepage for installation instructions.

Обзор реализацииImplementation overview

  1. Получение выдаваемого объекта Visual для принимающего элементаGet handout Visual for the host element
  2. Создание дерева эффекта размытия с помощью Win2D и CompositionEffectSourceParameterCreate a blur effect tree using Win2D and CompositionEffectSourceParameter
  3. Создание CompositionEffectBrush на основании дерева эффектаCreate a CompositionEffectBrush based on the effect tree
  4. Установка CompositionBackdropBrush в качестве входных данных для CompositionEffectBrush, что позволяет применить эффект к содержимому позади SpriteVisual.Set input of the CompositionEffectBrush to a CompositionBackdropBrush, which allows an effect to be applied to the content behind a SpriteVisual
  5. Установите CompositionEffectBrush в качестве содержимого нового объекта SpriteVisual и установите SpriteVisual в качестве дочернего элемента принимающего элемента.Set the CompositionEffectBrush as the content of a new SpriteVisual, and set the SpriteVisual as the child of the host element. Можно также использовать XamlCompositionBrushBase.You could alternative use a XamlCompositionBrushBase.
  6. Привязка размера SpriteVisual к размеру принимающего элемента с помощью ExpressionAnimationBind size of the SpriteVisual to the size of the host using an 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);
}

Дополнительные ресурсыAdditional Resources