[UWP]使用GetAlphaMask制作阴影
1. 前言
最近常常接触到GetAlphaMask,所以想写这篇文章介绍下GetAlphaMask怎么使用。其实GetAlphaMask的使用场景十分有限,Github上能搜到的内容都是用来配合DropShadow的,所以这篇文章也以介绍DropShadow为主。
2. 合成阴影
先介绍一下合成阴影。Compositor.CreateDropShadow()可以创建一个DropShadow,将这个DropShadowDropShadow赋值到SpriteVisual的Shadow属性,然后使用ElementCompositionPreview.SetElementChildVisual 将这个SpriteVisual设置到某个UIElement的可视化层里,再将这个UIElement放到需要阴影的元素后面,这样基本的合成阴影就完成了。
具体代码如下:
<Grid VerticalAlignment="Center"
HorizontalAlignment="Center">
<Grid x:Name="BackgroundGrid"/>
<Grid Background="Turquoise"
x:Name="Host">
<TextBlock Text="I need shadow"
Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="36"
Margin="16"/>
</Grid>
</Grid>
private readonly Compositor _compositor;
private readonly SpriteVisual _backgroundVisual;
private readonly DropShadow _dropShadow;
public MainPage() : base()
{
InitializeComponent();
_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
//创建并配置DropShadow
_dropShadow = _compositor.CreateDropShadow();
_dropShadow.BlurRadius = 16;
_dropShadow.Offset = new Vector3(8);
//创建SpriteVisual并设置Shadow
_backgroundVisual = _compositor.CreateSpriteVisual();
_backgroundVisual.Shadow = _dropShadow;
//将SpriteVisual放到可视化树
ElementCompositionPreview.SetElementChildVisual(BackgroundGrid, _backgroundVisual);
Host.SizeChanged += OnHostSizeChanged;
}
private void OnHostSizeChanged(object sender, SizeChangedEventArgs e)
{
Vector2 newSize = new Vector2(0, 0);
Vector3 centerPoint = new Vector3(0, 0, 0);
if (Host != null)
{
newSize = new Vector2((float)Host.ActualWidth, (float)Host.ActualHeight);
centerPoint = new Vector3((float)Host.ActualWidth / 2, (float)Host.ActualHeight / 2, 0);
}
_backgroundVisual.CenterPoint = centerPoint;
_backgroundVisual.Size = newSize;
}

3. 使用GetAlphaMask裁剪阴影
上面的代码需要可以实现阴影,但只能实现矩形的阴影,在WPF和Silverlight中常用的Shape的阴影,或者文字的阴影都做不出来。
例如将XAML改成这样的话,结果绝不是我想要的东西:
<Grid VerticalAlignment="Center"
HorizontalAlignment="Center">
<Grid x:Name="BackgroundGrid"/>
<TextBlock Text="I need shadow"
x:Name="Host"
Foreground="Turquoise"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="36"/>
</Grid>

这时候就需要用到GetAlphaMask这个函数。
Image、 TextBlock和Shape分别实现一个名为GetAlphaMask的方法, 该方法返回一个CompositionBrush , 该方法表示具有元素形状的灰度图像。
官当文档 中是这样描述GetAlphaMask函数的,简单来说就是拿到一个Image、TextBlock或Shape的轮廓,这个轮廓可以作为DropShadow.Mask的值,这样DropShadow的形状就可调用GetAlphaMask的元素的形状一样了。
具体代码和结果如下,这才是我想要的效果:
_dropShadow.Mask = Host.GetAlphaMask();

4. 使用DropShadowPanel
如果觉得自己写代码太过复杂, 可以使用Toolkit中的DropShadowPanel。

DropShadowPanel继承自ContentControl,当它的Cotnent为Shape、TextBlock、Image之一(或Toolkit中实现了GetAlphaMask的其它控件)时,它就调用GetAlphaMask获取阴影的形状,否则就是简单的举行,代码如下:
CompositionBrush mask = null;
if (Content is Image)
{
mask = ((Image)Content).GetAlphaMask();
}
else if (Content is Shape)
{
mask = ((Shape)Content).GetAlphaMask();
}
else if (Content is TextBlock)
{
mask = ((TextBlock)Content).GetAlphaMask();
}
else if (Content is ImageExBase imageExBase)
{
imageExBase.ImageExInitialized += ImageExInitialized;
if (imageExBase.IsInitialized)
{
imageExBase.ImageExInitialized -= ImageExInitialized;
mask = ((ImageExBase)Content).GetAlphaMask();
}
}
_dropShadow.Mask = mask;
之后它的做法和上面介绍的一样,把这个阴影设置到一个元素放在ContentPresenter后面,看起来就实现了Content的阴影:
_border = GetTemplateChild(PartShadow) as Border;
if (_border != null)
{
ElementCompositionPreview.SetElementChildVisual(_border, _shadowVisual);
}
<Grid Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}">
<Border x:Name="ShadowElement"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
5. 参考
将可视化层与 XAML 结合使用 - Windows UWP applications Microsoft Docs
Shape.GetAlphaMask Method (Windows.UI.Xaml.Shapes) - Windows UWP applications Microsoft Docs
DropShadow.Mask Property (Windows.UI.Composition) - Windows UWP applications Microsoft Docs
WindowsCommunityToolkit_Microsoft.Toolkit.Uwp.UI.Controls_DropShadowPanel at master
DropShadowPanel XAML Control - Windows Community Toolkit Microsoft Docs
[UWP]使用GetAlphaMask制作阴影的更多相关文章
- UWP Button添加圆角阴影(二)
原文:UWP Button添加圆角阴影(二) 阴影 对于阴影呢,WindowsCommunityToolkit中已经有封装好的DropShadowPanel啦,只要引用Microsoft.Toolki ...
- UWP Button添加圆角阴影(三)
原文:UWP Button添加圆角阴影(三) Composition DropShadow是CompositionAPI中的东西,使用Storyboard设置某个属性,就是频繁的触发put_xxx() ...
- UWP Button添加圆角阴影(一)
原文:UWP Button添加圆角阴影(一) 众所周知,17763之前的UWP控件,大部分是没有圆角属性的:而阴影也只有17763中的ThemeShadow可以直接在xaml中使用,之前的版本只能用D ...
- [UWP]使用GetAlphaMask和ContainerVisual制作长阴影(Long Shadow)
1. 什么是长阴影 前几年扁平化设计(Flat Design)十分流行,后来在扁平化的基础上又流行起了长阴影(Long Shadow).长阴影其实就是扩展了对象的投影,感觉是一种光线照射下的影子,通常 ...
- cocos2d-x 全面总结--字体描边和制作阴影
关于字体描边的实现,不考虑效果和效率的话,是有三种方式: ① 利用CCLabelTTF制作文字描边和阴影效果 ② 利用CCRenderTexture渲染文理的方式生成带有描边效果的文字 ③ 利用sha ...
- [UWP]为番茄钟应用设计一个平平无奇的状态按钮
1. 为什么需要设计一个状态按钮 OnePomodoro应用里有个按钮用来控制计时器的启动/停止,本来这应该是一个包含"已启动"和"已停止"两种状态的按钮,但我 ...
- Unity 阴影的制作方式
Unity阴影制作的三种方式. 方式一:Light中Shadow Type的类型 包括Hard Shadows.Soft Shadows.No Shadows: Mesh Renderer中的属性 ...
- box-shadow制作各种单边,多边阴影
一.box-shadow问题探究 box-shadow 在MDN定义以及详解: box-shadow 以由逗号分隔的列表来描述一个或多个阴影效果.该属性让你可以对几乎所有元素的边框产生阴影.如果元素同 ...
- [UWP]使用AlphaMaskEffect提升故障艺术动画的性能(顺便介绍怎么使用性能探测器分析UWP程序)
前几天发布了抄抄<CSS 故障艺术>的动画这篇文章,在这篇文章里介绍了如何使用Win2D绘制文字然后配合BlendEffect制作故障艺术的动画.本来打算就这样收手不玩这个动画了,但后来又 ...
随机推荐
- 抓住那只牛!Catch That Cow POJ-3278 BFS
题目链接:Catch That Cow 题目大意 FJ丢了一头牛,FJ在数轴上位置为n的点,牛在数轴上位置为k的点.FJ一分钟能进行以下三种操作:前进一个单位,后退一个单位,或者传送到坐标为当前位置两 ...
- 基于Linux系统--web环境搭建
上线部署文档 数据库部分1.下载Mysql服务 #yum install mysql-server 2.更改 /etc/my.cnf 3.启动Mysql ...
- 【Django】一对多表结构
1.创建project数据库表 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.co ...
- 3.form表单
1.Form标签:用来将表单外的内容与表单进行关联.其主要元素有input,button,select. action属性:指定表单的发送地址. Novalidate属性:数据提交时不校验. Targ ...
- MySQL 分页查询优化
有时在处理偏移量非常大的分页时候查询时,例如LIMIT 1000,10这样的查询,这时MySQL需要查询1010条记录然后只返回最后10条,前面1000条记录都被抛弃,这样的代价非常高.要优化这种查询 ...
- nginx 配置语法
一.语法规则: location [=|~|~*|^~] /uri/ { … } = 开头表示精确匹配 ^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可.nginx不对url做编码 ...
- Dropout原理与实现
Dropout是深度学习中的一种防止过拟合手段,在面试中也经常会被问到,因此有必要搞懂其原理. 1 Dropout的运作方式 在神经网络的训练过程中,对于一次迭代中的某一层神经网络,先随机选择中的一些 ...
- Bumblebee服务网关之统一请求验证
对于微服务网关来说,统一请求验证是一个比较重要和常用的功能,通过网关验证后台服务就无须关注请求验证:对于多语言平台的服务而言制定验证方式和变更验证配置都是一件比较繁琐和工作量大的事情.Bumblebe ...
- [Note] 解决使用Workerman和apache创建wss服务时出现的 Error during WebSocket handshake: net::ERR_RESPONSE_HEADERS_TRUNCATED
使用apache代理生成的wss服务常出现 Error during WebSocket handshake: net::ERR_RESPONSE_HEADERS_TRUNCATED 的问题,但多刷新 ...
- ActiveMQ学习总结------原生实战操作(下)03
本篇将继续延续上一篇的内容,作为知识补充篇,为接下来我们学习spring整合ActiveMQ打好基础 本篇主要学习内容: 1.ActiveMQ 队列服务监听 2.ActiveMQ Topic模型 回顾 ...