合成阴影

DropShadow 类提供了创建可应用于 SpriteVisualLayerVisual(视觉对象的子树)的可配置阴影的方法。 与视觉层中的对象一样,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;

具有 Basic DropShadow 的矩形视觉对象

塑造阴影

可通过几种方法为 DropShadow 定义形状:

  • 使用默认值 - 默认情况下,DropShadow 形状由 CompositionDropShadowSourcePolicy 上的“默认”模式定义。 对于 SpriteVisual,默认为矩形,除非提供了掩码。 对于 LayerVisual,默认值是继承一个掩码,具体方式为使用视觉对象的画笔的 alpha 通道。
  • 设置掩码 – 可以设置 Mask 属性来定义阴影的不透明度掩码。
  • 指定为使用继承掩码 – 将 SourcePolicy 属性设置为使用 CompositionDropShadowSourcePolicy。 InheritFromVisualContent 使用从视觉对象的画笔 alpha 生成的掩码。

屏蔽以匹配内容

如果希望阴影与Visual对象的内容匹配,可以使用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;

已连接的网络图像,带有遮罩的阴影效果

使用替代掩码

在某些情况下,你可能想要调整阴影,使其与视觉对象的内容不匹配。 若要达到此效果,需要使用具有 alpha 的画笔显式设置 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 属性进行动画处理。 下面,我们修改上面的洒水示例中的代码,以对阴影的模糊半径进行动画处理。

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

WinUI XAML 中的阴影

如果要向更复杂的框架元素添加阴影,可通过几种方法与 WinUI XAML 和合成之间的阴影进行互操作:

  1. 使用 CommunityToolkit.WinUI 包中可用的DropShadowPanel
  2. 创建视觉对象以用作阴影主机,并将其绑定到 XAML 交接视觉对象。
  3. 使用合成示例库的 SamplesCommon 自定义 CompositionShadow 控件。 有关用法,请参阅此处的示例。

性能

尽管视觉层有许多优化来使效果高效且可用,但生成阴影可能是一个相对昂贵的操作,具体取决于设置的选项。 下面是不同类型的阴影的总体“成本”。 请注意,虽然某些阴影可能很昂贵,但在某些情况下,它们可能仍适合谨慎使用。

阴影特征 Cost
矩形
阴影遮罩
CompositionDropShadowSourcePolicy.InheritFromVisualContent
静态模糊半径
对模糊半径进行动画处理

其他资源