Compartir a través de


Uso de la capa visual con XAML

La mayoría de las aplicaciones que consumen funcionalidades de capa visual usarán XAML para definir el contenido principal de la interfaz de usuario. En la actualización de aniversario de Windows 10, hay nuevas características en el marco XAML y la capa visual que facilitan la combinación de estas dos tecnologías para crear experiencias de usuario impresionantes. La funcionalidad de interoperabilidad xaml y de capa visual se puede usar para crear animaciones avanzadas y efectos no disponibles solo con las API XAML. Esto incluye:

  • Efectos de pincel como desenfoque y vidrio escarchado
  • Efectos de iluminación dinámica
  • Animaciones controladas por desplazamiento y parallax
  • Animaciones de diseño automático
  • Sombras paralelas precisas a nivel de píxel

Estos efectos y animaciones se pueden aplicar al contenido XAML existente, por lo que no tienes que reestructurar drásticamente tu aplicación XAML para aprovechar las nuevas funcionalidades. Las animaciones de diseño, las sombras y los efectos de desenfoque se tratan en la sección Recetas a continuación. Para obtener un ejemplo de código que implemente parallax, vea el ejemplo ParallaxingListItems. El repositorio WindowsCompositionSamples también tiene otros ejemplos para implementar animaciones, sombras y efectos.

La clase XamlCompositionBrushBase

XamlCompositionBrush proporciona una clase base para pinceles XAML que pintan un área con un CompositionBrush. Esto se puede usar para aplicar fácilmente efectos de composición como desenfoque o vidrio escarchado a elementos de la interfaz de usuario XAML.

Consulta la sección Pinceles para obtener más información sobre el uso de pinceles con la interfaz de usuario XAML.

Para obtener ejemplos de código, consulta la página de referencia de XamlCompositionBrushBase.

La clase XamlLight

XamlLight proporciona una clase base para los efectos de iluminación XAML que iluminan dinámicamente un área con un CompositionLight.

Consulta la sección Iluminación para obtener más información sobre el uso de luces, incluidos los elementos de la interfaz de usuario XAML de iluminación.

Para obtener ejemplos de código, consulta la página de referencia de XamlLight.

La clase ElementCompositionPreview

ElementCompositionPreview es una clase estática que proporciona funcionalidad de interoperabilidad xaml y de capa visual. Para obtener información general sobre la capa visual y su funcionalidad, consulte Capa visual. La clase ElementCompositionPreview proporciona los métodos siguientes:

  • GetElementVisual: obtener un objeto visual "handout" que se usa para representar este elemento
  • SetElementChildVisual: Configura un objeto visual "handin" como el último hijo del árbol visual de este elemento. Este objeto visual se dibujará sobre el resto del elemento.
  • GetElementChildVisual: recuperar el conjunto visual mediante SetElementChildVisual
  • GetScrollViewerManipulationPropertySet: conseguir un conjunto de propiedades que se puede usar para crear animaciones de 60 fps en función del desplazamiento en un ScrollViewer

Comentarios sobre ElementCompositionPreview.GetElementVisual

ElementCompositionPreview.GetElementVisual devuelve un objeto visual "handout" que se usa para representar el UIElement especificado. El marco XAML establece propiedades como Visual.Opacity, Visual.Offset y Visual.Size según el estado de UIElement. Esto permite técnicas como animaciones de reposición implícitas (vea Recetas).

Tenga en cuenta que, dado que Desplazamiento y tamaño se establecen como resultado del diseño del marco XAML, los desarrolladores deben tener cuidado al modificar o animar estas propiedades. Los desarrolladores solo deben modificar o animar Offset cuando la esquina superior izquierda del elemento tenga la misma posición que la de su elemento primario en el diseño. Por lo general, el tamaño no se debe modificar, pero el acceso a la propiedad puede ser útil. Por ejemplo, los ejemplos Drop Shadow and Frosted Glass debajo usan Size of a handout Visual como entrada para una animación.

Como advertencia adicional, las propiedades actualizadas del Visual no se reflejarán en el UIElement correspondiente. Por ejemplo, al establecer UIElement.Opacity en 0,5, se establecerá la opacidad del objeto visual correspondiente en 0,5. Sin embargo, si se establece el op acidad del objeto visual en 0,5, el contenido aparecerá en 50% opacidad, pero no cambiará el valor de la propiedad Opacity de UIElement correspondiente.

Ejemplo de animación de desplazamiento

Incorrecto

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

Correcto

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

Método ElementCompositionPreview.SetElementChildVisual

ElementCompositionPreview.SetElementChildVisual permite al desarrollador proporcionar un Visual específico, denominado "handin", que aparecerá como parte del árbol visual de un elemento. Esto permite a los desarrolladores crear una "Isla de composición" donde el contenido basado en objetos visuales puede aparecer dentro de una interfaz de usuario XAML. Los desarrolladores deben ser conservadores sobre el uso de esta técnica, ya que el contenido basado en objetos visuales no tendrá las mismas garantías de accesibilidad y experiencia del usuario de contenido XAML. Por lo tanto, se recomienda generalmente que esta técnica solo se use cuando sea necesario para implementar efectos personalizados como los que se encuentran en la sección Recetas a continuación.

Métodos de getAlphaMask

Image, TextBlock y Shape implementan un método denominado GetAlphaMask que devuelve un CompositionBrush que representa una imagen de escala de grises con la forma del elemento. Este CompositionBrush puede servir como entrada para una Composition DropShadow, de modo que la sombra puede reflejar la forma del elemento en lugar de un rectángulo. Esto permite sombras perfectas y basadas en contorno de píxeles para texto, imágenes con alfa y formas. Consulte Colocar sombra a continuación para obtener un ejemplo de esta API.

Recetas

Cambiar la posición de la animación

Con animaciones implícitas de composición, un desarrollador puede animar automáticamente los cambios en el diseño de un elemento en relación con su elemento primario. Por ejemplo, si cambia el margen del botón siguiente, se animará automáticamente a su nueva posición de diseño.

Información general sobre la implementación

  1. Obtener la hoja informativa Visual para el elemento de destino
  2. Cree una ImplicitAnimationCollection que anime automáticamente los cambios en la propiedad Offset.
  3. Asocie el ImplicitAnimationCollection con el objeto Visual de respaldo
<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;
}

Sombra paralela

Aplique una sombra paralela de píxeles perfecta a un UIElement, por ejemplo, una Elipse que contiene una imagen. Dado que la sombra requiere un SpriteVisual creado por la aplicación, es necesario crear un elemento "anfitrión", el cual contendrá el SpriteVisual mediante ElementCompositionPreview.SetElementChildVisual.

Información general sobre la implementación

  1. Consigue el documento Visual para el elemento host
  2. Crear un DropShadow de Windows.UI.Composition
  3. Configure el dropShadow de para obtener su forma del elemento de destino a través de una máscara
    • DropShadow es rectangular de forma predeterminada, por lo que no es necesario si el destino es rectangular.
  4. Adjunte la sombra a un nuevo SpriteVisualy establezca el spriteVisual de como elemento secundario del elemento host.
  5. Vincule el tamaño de SpriteVisual al tamaño del host usando un 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);
}

En las dos listas siguientes se muestran los C++/WinRT y C++/CX equivalentes del código de C# anterior con la misma estructura XAML.

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

Vidrio escarchado

Crea un efecto que desenfoque y tintiza el contenido de fondo. Tenga en cuenta que los desarrolladores deben instalar el paquete NuGet Win2D para usar efectos. Consulte el de la página principal de Win2D de para obtener instrucciones de instalación.

Información general sobre la implementación

  1. Obtener el documento Visual para el elemento host
  2. Crear un árbol de efectos de desenfoque con Win2D y CompositionEffectSourceParameter
  3. Crear una CompositionEffectBrush basada en el árbol de efectos
  4. Establezca la entrada del CompositionEffectBrush en un CompositionBackdropBrush, lo cual permite que se aplique un efecto al contenido detrás de una SpriteVisual.
  5. Establezca el CompositionEffectBrush como el contenido de un nuevo SpriteVisual, y luego establezca el SpriteVisual como elemento secundario del elemento host. Alternativamente, también puedes usar XamlCompositionBrushBase.
  6. Vincule el tamaño de SpriteVisual al tamaño del host usando un 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);
}

Recursos adicionales