XAML でのビジュアル レイヤーの使用Using the Visual Layer with XAML

ビジュアル レイヤーの機能を利用するほとんどのアプリは、XAML を使用して、メイン UI コンテンツを定義します。Most apps that consume Visual Layer capabilities will use XAML to define the main UI content. Windows 10 Anniversary Update では、XAML フレームワークやビジュアル レイヤーの新しい機能を利用し、これら 2 つのテクノロジを組み合わせて、魅力的なユーザー エクスペリエンスを簡単に作成することができます。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 とビジュアル レイヤーの相互運用機能を使用すると、XAML API 単独では実現できない、高度なアニメーションや効果を作成できます。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.

XamlCompositionBrushBase クラスThe XamlCompositionBrushBase class

XamlCompositionBrush は、CompositionBrush で領域をペイントする XAML ブラシの基底クラスを提供します。XamlCompositionBrush provides a base class for XAML brushes that paint an area with a CompositionBrush. これを使用することで、XAML UI 要素に、ぼかしやすりガラスなどのコンポジション効果を簡単に適用できます。This can be used to easily apply composition effects like blur or frosted glass to XAML UI elements.

XAML UI でのブラシの使い方について詳しくは、「ブラシ」セクションをご覧ください。See the Brushes section for more info on using brushes with XAML UI.

コードの例については、XamlCompositionBrushBase のリファレンス ページをご覧ください。For code examples, see the reference page for XamlCompositionBrushBase.

XamlLight クラスThe XamlLight class

XamlLight は、CompositionLight で領域を動的に照らす XAML 照明効果の基底クラスを提供します。XamlLight provides a base class for XAML lighting effects that dynamically light an area with a CompositionLight.

XAML UI 要素の照明など、ライトの使い方について詳しくは、「照明」セクションをご覧ください。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.

ElementCompositionPreview クラスThe ElementCompositionPreview class

ElementCompositionPreview は 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:この要素を表示するために使用される Visual「配布資料」を取得します。GetElementVisual: Get a "handout" Visual that is used to render this element
  • SetElementChildVisual:"Handin"最後の子としてのビジュアルのこの要素のビジュアル ツリーを設定します。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:ビジュアルのセットを使用して取得SetElementChildVisualGetElementChildVisual: Retrieve the Visual set using SetElementChildVisual
  • GetScrollViewerManipulationPropertySet:スクロールのオフセットに基づく 60 fps のアニメーションを作成するために使用できるオブジェクトを取得、 ScrollViewerGetScrollViewerManipulationPropertySet: Get an object that can be used to create 60fps animations based on scroll offset in a ScrollViewer

ElementCompositionPreview.GetElementVisual の解説Remarks on ElementCompositionPreview.GetElementVisual

ElementCompositionPreview.GetElementVisual は、指定の UIElement をレンダリングするために使用される "ハンドアウト" Visual を返します。ElementCompositionPreview.GetElementVisual returns a “handout” Visual that is used to render the given UIElement. Visual.OpacityVisual.OffsetVisual.Size などのプロパティは、UIElement の状態に基づいて、XAML フレームワークによって設定されます。Properties such as Visual.Opacity, Visual.Offset, and Visual.Size are set by the XAML framework based on the state of the UIElement. これにより、暗黙的な位置変更アニメーションなどの手法が利用可能になります (「Recipes」をご覧ください)。This enables techniques such as implicit reposition animations (see Recipes).

OffsetSize は 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 は変更しませんが、そのプロパティへアクセスすると便利な場合があります。Size should generally not be modified, but accessing the property may be useful. たとえば、以下に示すドロップ シャドウやすりガラスのサンプルでは、ハンドアウト Visual の Size をアニメーションへの入力として使用します。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 の Opacity も 0.5 に設定されます。So for example, setting UIElement.Opacity to 0.5 will set the corresponding handout Visual’s Opacity to 0.5. ただし、ハンドアウト Visual の Opacity を 0.5 に設定した場合、コンテンツが 50% の不透明度で表示されますが、対応する UIElement の Opacity プロパティの値は変更されません。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.

オフセット アニメーションの例Example 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.SetElementChildVisual メソッドThe 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 UI 内部に表示できる、"コンポジション アイランド" を作成できます。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.

GetAlphaMask メソッドGetAlphaMask methods

イメージ TextBlock、および図形と呼ばれるメソッドを実装する各GetAlphaMaskを返す、 CompositionBrush要素の形状を持つ、グレースケール イメージを表します。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. Offset プロパティの変更を自動的にアニメーション化する ImplicitAnimationCollection を作成しますCreate an ImplicitAnimationCollection that automatically animates changes in the Offset property
  3. ImplicitAnimationCollection をバッキング Visual に関連付けますAssociate 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 (たとえば、画像を含んでいる楕円) に適用します。Apply a pixel-perfect drop shadow to a UIElement, for example an Ellipse containing a picture. シャドウでは、アプリで作成される SpriteVisual が必要となるため、ElementCompositionPreview.SetElementChildVisual を使用して、SpriteVisual が含まれる “ホスト” 要素を作成する必要があります。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. Windows.UI.Composition の DropShadow を作成しますCreate 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. ExpressionAnimation を使用して、SpriteVisual のサイズをホストのサイズにバインドしますBind 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);
}

次の 2 つの一覧では、同じ XAML 構造を使用する、以前の C# コードと同等の C++/WinRT および C++/CX を示しています。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 と CompositionEffectSourceParameter を使用して、ぼかし効果ツリーを作成しますCreate a blur effect tree using Win2D and CompositionEffectSourceParameter
  3. 効果ツリーに基づいて CompositionEffectBrush を作成しますCreate a CompositionEffectBrush based on the effect tree
  4. CompositionEffectBrush の入力を CompositionBackdropBrush に設定します。これにより、効果が 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. ExpressionAnimation を使用して、SpriteVisual のサイズをホストのサイズにバインドしますBind 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