Sombras de composición

La clase DropShadow proporciona medios para crear una sombra configurable que se puede aplicar a un SpriteVisual o LayerVisual (subárbol de objetos visuales). Como es habitual para los objetos de la capa visual, todas las propiedades de DropShadow se pueden animar mediante CompositionAnimations.

Sombra paralela básica

Para crear una sombra básica, simplemente cree una nueva DropShadow y asóciela al objeto visual. La sombra es rectangular de forma predeterminada. Está disponible un conjunto estándar de propiedades para ajustar el aspecto y la sensación de tu sombra.

var basicRectVisual = _compositor.CreateSpriteVisual();
basicRectVisual.Brush = _compositor.CreateColorBrush(Colors.Blue);
basicRectVisual.Offset = new Vector3(100, 100, 20);
basicRectVisual.Size = new Vector2(300, 300);

var basicShadow = _compositor.CreateDropShadow();
basicShadow.BlurRadius = 25f;
basicShadow.Offset = new Vector3(20, 20, 20);

basicRectVisual.Shadow = basicShadow;

Objeto visual rectangular con sombra de fondo básica

Dar forma a la sombra

Hay varias maneras de definir la forma para dropShadow:

  • Use el valor predeterminado - De forma predeterminada, la forma DropShadow está definida por el modo «Default» en CompositionDropShadowSourcePolicy. Para SpriteVisual, el valor predeterminado es Rectangular a menos que se proporcione una máscara. Para LayerVisual, el valor predeterminado es heredar una máscara utilizando el alfa del pincel visual.
  • Establecer una máscara : puede establecer la propiedad Mask para definir una máscara de opacidad para la sombra.
  • Especifique para usar la máscara heredada : establezca la propiedad SourcePolicy para usar CompositionDropShadowSourcePolicy. InheritFromVisualContent para usar la máscara generada a partir del alfa del pincel del objeto visual.

Enmascaramiento para que coincida con el contenido

Si desea que la sombra coincida con el contenido del Visual, puede usar el pincel del Visual para la propiedad de máscara de sombra o establecer la sombra para heredar automáticamente la máscara del contenido. Si usa layerVisual, la sombra heredará la máscara de forma predeterminada.

var imageSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/myImage.png"));
var imageBrush = _compositor.CreateSurfaceBrush(imageSurface);

var imageSpriteVisual = _compositor.CreateSpriteVisual();
imageSpriteVisual.Size = new Vector2(400,400);
imageSpriteVisual.Offset = new Vector3(100, 500, 20);
imageSpriteVisual.Brush = imageBrush;

var shadow = _compositor.CreateDropShadow();
shadow.Mask = imageBrush;
// or use shadow.SourcePolicy = CompositionDropShadowSourcePolicy.InheritFromVisualContent;
shadow.BlurRadius = 25f;
shadow.Offset = new Vector3(20, 20, 20);

imageSpriteVisual.Shadow = shadow;

Imagen web vinculada con sombra paralela enmascarada

Uso de una máscara alternativa

En algunos casos, es posible que desee ajustar la forma de la sombra para que no coincida con el contenido de su visual. Para lograr este efecto, deberá establecer explícitamente la propiedad Mask mediante un pincel con alfa.

En el ejemplo siguiente, cargamos dos superficies: una para el contenido visual y otra para la máscara de sombra:

var imageSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/myImage.png"));
var imageBrush = _compositor.CreateSurfaceBrush(imageSurface);

var circleSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/myCircleImage.png"));
var customMask = _compositor.CreateSurfaceBrush(circleSurface);

var imageSpriteVisual = _compositor.CreateSpriteVisual();
imageSpriteVisual.Size = new Vector2(400,400);
imageSpriteVisual.Offset = new Vector3(100, 500, 20);
imageSpriteVisual.Brush = imageBrush;

var shadow = _compositor.CreateDropShadow();
shadow.Mask = customMask;
shadow.BlurRadius = 25f;
shadow.Offset = new Vector3(20, 20, 20);

imageSpriteVisual.Shadow = shadow;

Imagen web conectada con sombra paralela enmascarada en forma de círculo

Animación

Como es estándar en la capa visual, las propiedades DropShadow se pueden animar mediante animaciones de composición. A continuación, modificamos el código de la muestra de sprinkles anterior para animar el radio de desenfoque de la sombra.

ScalarKeyFrameAnimation blurAnimation = _compositor.CreateScalarKeyFrameAnimation();
blurAnimation.InsertKeyFrame(0.0f, 25.0f);
blurAnimation.InsertKeyFrame(0.7f, 50.0f);
blurAnimation.InsertKeyFrame(1.0f, 25.0f);
blurAnimation.Duration = TimeSpan.FromSeconds(4);
blurAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
shadow.StartAnimation("BlurRadius", blurAnimation);

Sombras en WinUI XAML

Si deseas agregar una sombra a elementos del marco más complejos, hay un par de maneras de interactuar con sombras entre WinUI XAML y Composition.

  1. Use el DropShadowPanel disponible en el paquete CommunityToolkit.WinUI.
  2. Cree un objeto visual para usar como host de sombras y vincúlelo al objeto visual de intercambio XAML.
  3. Utilice el control personalizado CompositionShadow de SamplesCommon de la Galería de muestras de composición. Consulte el ejemplo aquí para su uso.

Rendimiento

Aunque la capa visual tiene muchas optimizaciones para hacer que los efectos sean eficaces y utilizables, la generación de sombras puede ser una operación relativamente costosa en función de las opciones que establezca. A continuación se muestran los "gastos" de nivel general para diferentes tipos de sombras. Tenga en cuenta que, aunque ciertas sombras pueden ser costosas, pueden seguir siendo adecuadas para usar con moderación en determinados escenarios.

Características de sombra Costo
Rectangular Low
Sombra.Máscara Alto
CompositionDropShadowSourcePolicy.InheritFromVisualContent Alto
Radio de desenfoque estático Low
Animar el radio de desenfoque Alto

Recursos adicionales