前言
2021年6月24日,随着微软正式宣布 Windows 11 作为下一代 Windows 的大版本更新, 更新的流畅设计体系 Fluent Design System 也通过 WinUI 库 2.6 版本与大家见面. 本文探讨其中 "动态图标 AnimatedIcon
" 板块的具体内容.
背景
其实这套AnimatedIcon的实现途径并不新鲜. 早在很久以前的Windows Community Toolkit
中, 我们便已在 Lottie-Windows 中见过. Lottie 是 Airbnb 公司推出的一款动画实现工具, 用于为各平台原生应用提供动画支持, 通用型极强. 我们只需使用 Adobe After Effects 配合 Bodymovin 插件即可制作优美, 通用于各平台的动画.
开发环境
若工具版本低于笔者版本, 无法确保各项功能可用. 如果工具发生更新, 也无法确保功能仍然可用.
- Windows 10 Version 21H1
- Visual Studio 2019 (v16.10.4)
- .Net (v5.0.302) [.Net 5.0 必需]
- NuGet Package: Microsoft.UI.Xaml (v2.6.1)
- macOS Big Sur 11.4
- Adobe After Effects 2021 (v18.2.1)
- AE Plugin: Bodymovin (v5.7.12) 安装参考
同时, 请确保你的UWP项目使用的C#语言版本高于v9.0 (后文详述原因).
步骤一: 使用 After Effects 制作动画
创建好合成即可. 注意合成的帧率和时间. 此处不赘述.
但请注意创建的动画必须满足生成 Lottie 动画文件的条件. 具体支持在这里.
请务必优化动画的性能, 以最小的代价达到最优效果.
步骤二: 使用 Bodymovin 插件制作 Lottie 的 json 文件
安装好 Bodymovin 后在 After Effects 中依次点击 菜单栏"窗口" - “扩展” - “Bodymovin”, 启动转换工具.
接着在打开的窗口中选中你需要生成的合成, 设置 json 文件存储的目标路径, 如无特别需求无需更改合成项导出相关设置 (至少在本项目中是如此).
准备就绪后点击 Render 即导出了 Lottie 的目标文件, 格式为 json.
步骤三: 根据需求修改导出的文件
与社区工具包中的 Lottie 不同的是, AnimatedIcon
支持根据指针事件控制动画的播放, 这极大减少了开发人员的工作量, 只需在 json 文件中进行定义即可完成不同操作的动画反馈.
此处我们仅关注文件末尾的 markers
字段. 根据官方文档的描述:
You can also define markers in the animation definition to indicate playback time positions. You can then set the AnimatedIcon state to these markers. For example, if you have a playback position in the Lottie file marked “PointerOver”, you can set the AnimatedIcon state to “PointerOver” and move the animation to that playback position.
For example, the AutoSuggestBox control uses an AnimatedIcon that animates with the following states:
- Normal
- PointerOver
- Pressed
You can define markers in your Lottie file with those state names. You can also define markers as follows:
Insert “To” between state names. For example, if you define a “NormalToPointerOver” marker, changing the AnimatedIcon state from “Normal” to “PointerOver” will cause it to move to this marker’s playback position.
Append “_Start” or “_End” to a marker name. For example defining markers “NormalToPointerOver_Start” and “NormalToPointerOver_End” and changing the AnimatedIcon state from “Normal” to “PointerOver” will cause it to jump to the _Start marker’s playback position and then animate to the _End playback position.
大致解释一下, 定义 markers
的方式有两种: 点定位和段定位 (为描述方便, 自命名之).
点定位即声明每种状态所处帧数位置, 定义简单, 但不适用于较复杂动画. 两状态的切换只有顺序播放和倒序播放. 模板:
"markers": [
{ "tm": 0, "cm": "Normal", "dr": 0 },
{ "tm": 0, "cm": "PointerOver", "dr": 0 },
{ "tm": 0, "cm": "Pressed", "dr": 0 }
]
具体帧数在 tm
(?好名字) 指定即可.
段定位需要指定不同指针状态的过渡动画. 定义稍繁琐, 定义时 “cm” 字段需要用 “StateToState_Start/End
” 的形式显式指定动画的起点/终点, 优点是十分灵活, 可自由定义动画的进行, 适应复杂的视觉反馈. 模板:
"markers": [
{ "tm": 0, "cm": "NormalToPointerOver_Start", "dr": 0 }, { "tm": 0, "cm": "NormalToPointerOver_End", "dr": 0 },
{ "tm": 0, "cm": "NormalToPressed_Start", "dr": 0 }, { "tm": 0, "cm": "NormalToPressed_End", "dr": 0 },
{ "tm": 0, "cm": "PointerOverToNormal_Start", "dr": 0 }, { "tm": 0, "cm": "PointerOverToNormal_End", "dr": 0 },
{ "tm": 0, "cm": "PointerOverToPressed_Start", "dr": 0 }, { "tm": 0, "cm": "PointerOverToPressed_End", "dr": 0 },
{ "tm": 0, "cm": "PressedToNormal_Start", "dr": 0 }, { "tm": 0, "cm": "PressedToNormal_End", "dr": 0 },
{ "tm": 0, "cm": "PressedToPointerOver_Start", "dr": 0 }, { "tm": 0, "cm": "PressedToPointerOver_End", "dr": 0 }
]
帧数定义同上.
根据动画设计自行选择即可.
步骤四: 使用 LottieGen 工具生成 C# 类
在 AnimatedIcon
中我们不再使用工具包中传统的 AnimatedVisualPlayer
来进行动画的展示. 这里介绍 LottieGen 工具. 它可以直接将 Lottie 文件转换为我们可用的 C# 类嵌入项目, 生成的类实现了 IAnimatedVisualSource
接口, 可直接作为 AnimatedIcon
的 Source
在 XAML 中显示.
首先确保 Windows 平台安装了 .Net 5.0 (官方要求). 下载页面
在命令行输入:
dotnet tool install -g LottieGen
导航至 Lottie 文件所在目录后, 运行以下指令:
lottiegen -InputFile 「Lottie文件名」 -Language cs
对于此项目, 笔者运行的是:
lottiegen -InputFile SettingsAnimatedIcon.json -Lanuguage cs -WinUIVersion 2.6 -GenerateColorBindings -MinimumUapVersion 7
解释:
-WinUIVersion 2.6
设置 WinUI 版本, 以匹配项目中 WinUI 的版本. LottieGen 默认为 WinUI 2.4 生成, 生成的类仅实现IAnimatedVisualSource
接口, 而 WinUI 2.6 要求的IAnimatedVisualSource2
未实现, 编译报错.-GenerateColorBindings
生成动画元素的颜色绑定. 具体后文介绍.-MinimumUapVersion 7
此处UAP版本可参照我的这篇文章,项目支持最低Windows版本为1809,因此Uap最低版本为7.
至此, 我们便在 Lottie 文件的目录下得到了包含目标类的 cs 文件.
步骤五: 在项目中使用类文件
笔者在项目的NavigationView中使用动画图标. XAML 代码如下:
<!--xmlns:animatedvisuals="using:AnimatedVisuals"-->
<muxc:NavigationViewItem Content = "Settings">
<muxc:NavigationViewItem.Icon>
<muxc:AnimatedIcon>
<muxc:AnimatedIcon.Source>
<animatedvisuals:SettingsAnimatedIcon />
</muxc:AnimatedIcon.Source>
<muxc:AnimatedIcon.FallbackIconSource>
<muxc:FontIconSource FontFamily="Segoe MDL2 Assets" Glyph=""/>
</muxc:AnimatedIcon.FallbackIconSource>
</muxc:AnimatedIcon>
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
XAML中应加入命名空间引用, LottieGen 默认生成的命名空间均为 AnimatedVisuals
, 如有需要也可以更改. (在生成命令中加上 -Namespace XXXXX
即可.)
至此, 动态图标已在UWP中实现.
步骤六: 明暗主题适配
注: 此步骤仅用于黑白图标. 其他配色需要单独设计.
此前生成的图标是不支持主题自适应的. 它仅仅会显示为第一步在 After Effects 中制作动画时使用的配色. 我们可以通过修改 C# 类达到目的. 官方推荐我们定义 “Foreground” 字段实现颜色自适应, 这里提供一个更简单的方法.
在第四步中我们通过-GenerateColorBindings
生成了动画元素的颜色绑定. 类中定义了方法 SetColorProperty()
, 通过传入颜色名称改变元素颜色. 方法定义如下:
/// <summary>
/// Sets the color property with the given name, or does nothing if no such property exists.
/// </summary>
public void SetColorProperty(string propertyName, Color value)
{
if (propertyName == "Color_000000")
{
_themeColor_000000 = value;
}
else
{
return;
}
if (_themeProperties is not null)
{
_themeProperties.InsertVector4(propertyName, ColorAsVector4(value));
}
}
注: 此处 LottieGen 工具自动生成的代码中包含了 is not
关键字, 仅在 C# 9.0 版本以上可用, 为避免反复修改, 建议将项目语言版本修改至 9.0 .
在该方法中断点调试, 得知生成动画元素以及系统主题切换时调用该方法, 传入参数 propertyName
的值为 "Foreground"
. 由于动画元素中仅有一个前景色, 我们可直接将 Foreground 重定向至该颜色, 在方法开头添加一句
if (propertyName == "Foreground") propertyName = "Color_000000";
万事大吉. 此后系统对图标的 Foreground 进行修改时, 所有默认为黑色的元素均会调整为系统前景色. XAML 中无需进行任何修改. Over.
总结
WinUI 2.6 在此前基础上大大强化了 Lottie 在 Windows 平台上的实用性, 插入动态效果也变得十分简洁, 相比以前减少了许多代码量, 点个赞. LottieGen 官方文档描述较简单, 功能可以通过 lottiegen -Help
具体查看, 此处不赘述. 预祝 Windows 11 和新一代设计体系取得成功.
转载请注明来源。
文章地址 https://blog.csdn.net/brandonw3612/article/details/119399450