Sombras de composição

A classe DropShadow fornece meios de criar uma sombra configurável que pode ser aplicada a um SpriteVisual ou LayerVisual (subárvore de visuais). Como é de costume para objetos na Camada Visual, todas as propriedades do DropShadow podem ser animadas usando CompositionAnimations.

Sombra projetada básica

Para criar uma sombra básica, basta criar um novo DropShadow e associá-lo ao seu visual. A sombra é retangular por padrão. Um conjunto padrão de propriedades está disponível para ajustar a aparência de sua 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;

Visual retangular com DropShadow básico

Formando a sombra

Há algumas maneiras de definir a forma para seu DropShadow:

  • Use o padrão – por padrão, a forma DropShadow é definida pelo modo 'Default' em CompositionDropShadowSourcePolicy. Para SpriteVisual, o padrão é Retangular, a menos que uma máscara seja fornecida. Para LayerVisual, o padrão é herdar uma máscara usando o alpha do pincel do LayerVisual.
  • Definir uma máscara – você pode definir a propriedade Mask para definir uma máscara de opacidade para a sombra.
  • Especificar o uso da máscara herdada – Defina a propriedade SourcePolicy para utilizar CompositionDropShadowSourcePolicy. InheritFromVisualContent para usar a máscara gerada a partir do canal alfa do pincel visual.

Mascaramento para corresponder ao seu conteúdo

Se você quiser que sua sombra corresponda ao conteúdo do Visual, você tem a opção de usar o pincel do Visual como propriedade da máscara de sombra ou definir a sombra para herdar automaticamente a máscara do conteúdo. Se estiver usando um LayerVisual, a sombra herdará a máscara por padrão.

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;

Imagem da web conectada com sombra projetada mascarada

Usando uma máscara alternativa

Em alguns casos, talvez você queira moldar a sombra de modo que ela não corresponda ao conteúdo do visual. Para obter esse efeito, você precisará definir explicitamente a propriedade Mask usando um pincel com alfa.

No exemplo abaixo, carregamos duas superfícies : uma para o conteúdo visual e outra para a máscara 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;

Imagem da Web conectada com sombra projetada mascarada em forma de círculo

Animação em andamento

Como é padrão na Camada Visual, as propriedades DropShadow podem ser animadas usando animações de composição. Abaixo, modificamos o código do exemplo de sprinkles acima para animar o raio de desfoque da 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 no WinUI XAML

Se você quiser adicionar uma sombra a elementos de estrutura mais complexos, há algumas maneiras de interoperabilidade com sombras entre o WinUI XAML e a Composição:

  1. Use o DropShadowPanel disponível no pacote CommunityToolkit.WinUI.
  2. Crie um Visual para usar como o host de sombra e vincule-o ao visual de entrega XAML.
  3. Use o controle personalizado CompositionShadow SamplesCommon da Galeria de Exemplos de Composição. Veja o exemplo aqui para uso.

Desempenho

Embora a Camada Visual tenha muitas otimizações em vigor para tornar os efeitos eficientes e utilizáveis, gerar sombras pode ser uma operação relativamente cara, dependendo das opções definidas. Abaixo estão as estimativas de custos de alto nível para diferentes tipos de sombras. Observe que, embora determinadas sombras possam ser caras, elas ainda podem ser apropriadas para usar com moderação em determinados cenários.

Características de sombra Custo
Retangular Baixo
Máscara de Sombra Alto
CompositionDropShadowSourcePolicy.InheritFromVisualContent Alto
Raio de Desfoque Estático Baixo
Animação do raio de desfoque Alto

Recursos adicionais