Композиционные тени

Класс DropShadow предоставляет средства создания настраиваемой тени, которую можно применить к SpriteVisual или LayerVisual (поддерево визуальных элементов). Как и обычно для объектов в визуальном слое, все свойства DropShadow могут быть анимированы с помощью CompositionAnimations.

Базовая тень

Чтобы создать базовую тень, просто создайте новый DropShadow и свяжите его с визуальным элементом. По умолчанию тень является прямоугольной. Стандартный набор свойств доступен для настройки внешнего вида и чувства тени.

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;

Прямоугольный графический объект с базовой падающей тенью

Формирование тени

Существует несколько способов определить фигуру для dropShadow:

  • Используйте значение по умолчанию. По умолчанию фигура DropShadow определяется режимом default в CompositionDropShadowSourcePolicy. Для SpriteVisual значение по умолчанию является прямоугольным, если не указана маска. По умолчанию для LayerVisual наследуется маска с использованием альфа-канала кисти визуального элемента.
  • Задайте маску — можно задать свойство Mask , чтобы определить маску непрозрачности для тени.
  • Укажите использование унаследованной маски — установите свойство SourcePolicy на CompositionDropShadowSourcePolicy. InheritFromVisualContent для использования маски, созданной из альфа-канала кисти визуального элемента.

Маскирование для сопоставления содержимого

Если вы хотите, чтобы тень соответствовала содержимому компонента Visual, вы можете использовать кисть компонента для свойства маски тени или задать тени автоматическое наследование маски от содержимого. При использовании LayerVisual тень будет наследовать маску по умолчанию.

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;

Связанный веб-изображение с замаскированной теневой областью

Использование альтернативной маски

В некоторых случаях может понадобиться сформировать тень таким образом, чтобы она не соответствовала содержимому визуального компонента. Чтобы добиться этого эффекта, необходимо явно задать свойство Mask с помощью кисти с альфа-символом.

В приведенном ниже примере мы загружаем две поверхности — одну для визуального содержимого и одну для маски тени:

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;

Связанное веб-изображение с закругленной маскировкой и тенью

Анимации

Как и в стандартном визуальном слое, свойства DropShadow можно анимировать с помощью анимации композиции. Ниже мы изменим код из приведенного выше примера с "sprinkles", чтобы анимировать радиус размытия для тени.

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

Тени в XAML WinUI

Если вы хотите добавить тень к более сложным элементам платформы, существует несколько способов взаимодействия с тенями между WinUI XAML и Composition:

  1. Используйте компонент DropShadowPanel, доступный в пакете CommunityToolkit.WinUI.
  2. Создайте визуальный элемент для использования в качестве теневого узла и привязать его к визуальному элементу XAML.
  3. Используйте пользовательский элемент управления CompositionShadow из SamplesCommon галереи Composition Sample. См. пример использования.

Производительность

Хотя визуальный слой имеет много оптимизаций для эффективного использования, создание теней может быть относительно дорогой операцией в зависимости от того, какие параметры вы задали. Ниже приведены высокие "затраты" для различных типов теней. Обратите внимание, что хотя некоторые тени могут быть дорогостоящими, они по-прежнему могут быть подходящими для использования в определённых ситуациях.

Характеристики тени Cost
Прямоугольный Low
Тень.Маска High
CompositionDropShadowSourcePolicy.InheritFromVisualContent High
Статический радиус размытия Low
Анимация радиуса размытия High

Дополнительные ресурсы