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. Esta característica 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 de colocación perfectas para píxeles
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 ver ejemplos de código, consulta la página de referencia correspondiente a XamlCompositionBrushBase.
La clase XamlLight
XamlLight proporciona una clase base para los efectos de iluminación XAML que iluminan dinámicamente un área con 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: establece un objeto visual "handin" como último elemento secundario del árbol visual de este elemento. Este objeto visual se dibujará sobre el resto del elemento.
- GetElementChildVisual: recuperar el conjunto visual mediante SetElementChildVisual
- GetScrollViewerManipulationPropertySet: obtener un objeto que se puede usar para crear animaciones de 60fps basadas en el desplazamiento de desplazamiento en un ScrollViewer
Comentarios en 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 (consulte Recetas).
Tenga en cuenta que, dado que Offset y Size 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 objeto visual de documentos no se reflejarán en el UIElement correspondiente. Por ejemplo, si se establece UIElement.Opacity en 0,5, se establecerá la opacidad del objeto visual correspondiente en 0,5. Sin embargo, establecer la opacidad del objeto visual del documento en 0,5 hará que el contenido aparezca en el 50 % de opacidad, pero no cambiará el valor de la propiedad Opacity de UIElement correspondiente.
Ejemplo de animación offset
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);
El método ElementCompositionPreview.SetElementChildVisual
ElementCompositionPreview.SetElementChildVisual permite al desarrollador proporcionar un objeto visual "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 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 DropShadow de composición, por lo 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
- Obtener el objeto visual de documento para el elemento de destino
- Crear una ImplicitAnimationCollection que anima automáticamente los cambios en la propiedad Offset
- Asociar 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 de colocación perfecta de píxeles 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 "host", que contendrá SpriteVisual mediante ElementCompositionPreview.SetElementChildVisual.
Información general sobre la implementación
- Obtener el objeto visual del documento para el elemento host
- Crear una dropShadow de Windows.UI.Composition
- Configurar DropShadow 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.
- Adjunte sombra a un nuevo SpriteVisual y establezca SpriteVisual como elemento secundario del elemento host.
- Enlace del tamaño de SpriteVisual al tamaño del host mediante 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 equivalentes de C++/WinRT y C++/CX 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 la página principal de Win2D para obtener instrucciones de instalación.
Información general sobre la implementación
- Obtención del objeto visual de documentos para el elemento host
- Creación de un árbol de efectos de desenfoque mediante Win2D y CompositionEffectSourceParameter
- Creación de un compositionEffectBrush basado en el árbol de efectos
- Establezca la entrada de CompositionEffectBrush en compositionBackdropBrush, lo que permite aplicar un efecto al contenido detrás de spriteVisual.
- Establezca CompositionEffectBrush como el contenido de un nuevo SpriteVisual y establezca SpriteVisual como elemento secundario del elemento host. También puedes usar xamlCompositionBrushBase.
- Enlace del tamaño de SpriteVisual al tamaño del host mediante 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
- Introducción a la capa visual
- Clase ElementCompositionPreview
- Ejemplos avanzados de interfaz de usuario y composición en GitHub WindowsCompositionSamples
- Ejemplo de BasicXamlInterop
- Ejemplo parallaxingListItems