Microsoft.UI.Composition API 允许将实时效果应用于具有动画效果属性的图像和 UI。 在本概述中,我们将逐步讲解使你能够在 WinUI 和 Windows 应用 SDK 应用中将效果应用于合成视觉对象的功能。
为了支持 WinUI 和 Windows 应用 SDK 应用中的一致效果创作,合成效果利用 Win2D 的 IGraphicsEffect 接口,以便可以使用 Microsoft.Graphics.Canvas.Effects 命名空间来描述效果。
画笔效果用于通过将效果应用于一组现有图像来绘制应用程序的区域。 Windows 应用 SDK 组合效果 API 侧重于 SpriteVisuals。 在组合颜色、图像和效果创建时,SpriteVisual 提供灵活性。 视觉对象定义矩形的边界,画笔定义用于绘制矩形的像素。
效果画笔用于其内容来自效果图输出的合成树视觉对象。 效果可以引用现有表面/纹理,但不能引用其他合成树的输出。
效果还可以通过使用效果画笔与XamlCompositionBrushBase应用于XAML UIElements。
效果功能
效果库
当前合成支持以下效果:
| Effect | 说明 |
|---|---|
| 2D 仿射转换 | 将 2D 仿射转换矩阵应用于图像。 |
| 算术合成 | 使用灵活的公式合并两个图像。 |
| 混合效果 | 创建合并两个图像的混合效果。 合成提供 Win2D 中支持的 26 种 混合模式 中的 21 种。 |
| 颜色源 | 创建包含纯色的图像。 |
| 复合 | 合并两个图像。 合成提供 Win2D 中支持的所有 13 种复合模式 。 |
| 对比度 | 增加或减少图像的对比度。 |
| 曝光 | 增加或减少图像的曝光率。 |
| 灰度 | 将图像转换为单色灰色。 |
| 伽玛转移 | 通过应用每通道伽玛传输函数来更改图像的颜色。 |
| 色调旋转 | 通过旋转图像的色调值来更改图像的颜色。 |
| 反转 | 反转图像的颜色。 |
| 饱和 | 更改图像的饱和度。 |
| 棕 褐色 | 将图像转换为棕褐色调。 |
| 温度和色调 | 调整图像的温度和/或色调。 |
有关更多详细信息,请参阅 Win2D 的 Microsoft.Graphics.Canvas.Effects 命名空间。 合成中不支持的效果被记录为 [NoComposition]。
链式效应
可以链接效果,使应用程序能够同时对图像使用多个效果。 效果图可以支持多个效果,这些效果可以相互引用。 描述您的效果时,只需将一个效果作为输入添加到您的效果中。
IGraphicsEffect graphicsEffect =
new Microsoft.Graphics.Canvas.Effects.ArithmeticCompositeEffect
{
Source1 = new CompositionEffectSourceParameter("source1"),
Source2 = new SaturationEffect
{
Saturation = 0,
Source = new CompositionEffectSourceParameter("source2")
},
MultiplyAmount = 0,
Source1Amount = 0.5f,
Source2Amount = 0.5f,
Offset = 0
}
上面的示例描述了具有两个输入的算术复合效果。 第二个输入具有饱和度为0.5的饱和效果。
动画支持
效果属性支持动画。在效果编译期间,可以指定哪些效果属性能够进行动画,哪些可以作为常量“烘焙”进其中。 可通过格式为“effect name.property name”的字符串指定可动画属性。 这些属性可以在效果的多个实例化上独立进行动画处理。
常量与动画效果属性
在效果编译期间,您可以将效果属性指定为动态属性,也可以作为常量嵌入的属性。 动态属性是通过格式为“效果名称<”>的字符串指定的。<属性名称>”。 动态属性可以设置为特定值,也可以使用合成动画系统进行动画处理。
在编译上述效果说明时,你可以选择将饱和度固定为0.5,或者将其设置为动态,并进行动态调整或动画处理。
将饱和度整合到效果中的编译过程:
var effectFactory = _compositor.CreateEffectFactory(graphicsEffect);
使用动态饱和度编译效果:
var effectFactory = _compositor.CreateEffectFactory(graphicsEffect, new[]{"SaturationEffect.Saturation"});
_catEffect = effectFactory.CreateBrush();
_catEffect.SetSourceParameter("mySource", surfaceBrush);
_catEffect.Properties.InsertScalar("saturationEffect.Saturation", 0f);
然后,可以将上述效果的饱和属性设置为静态值,或使用 Expression 或 ScalarKeyFrame 动画进行动画处理。
可以创建一个 ScalarKeyFrame,用于对效果的饱和度属性进行动画处理,如下所示:
ScalarKeyFrameAnimation effectAnimation = _compositor.CreateScalarKeyFrameAnimation();
effectAnimation.InsertKeyFrame(0f, 0f);
effectAnimation.InsertKeyFrame(0.50f, 1f);
effectAnimation.InsertKeyFrame(1.0f, 0f);
effectAnimation.Duration = TimeSpan.FromMilliseconds(2500);
effectAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
在效果的饱和度属性上启动动画,如下所示:
catEffect.Properties.StartAnimation("saturationEffect.Saturation", effectAnimation);
具有独立属性的多个效果实例
通过指定参数在效果编译过程中应为动态参数,然后可以基于每个效果实例更改该参数。 这允许两个视觉对象使用相同的效果,但呈现效果属性不同。
合成效果入门
本快速入门教程介绍如何使用效果的一些基本功能。
安装 Visual Studio
- 如果尚未安装受支持的 Visual Studio 版本,请转到 此处的 Visual Studio 下载页面。
创建新项目
- 转到“文件”>“新建”>“项目”。
- 选择 空白应用,打包(在桌面中使用 WinUI 3) 模板,或者选择 空白应用,未打包(在桌面中使用 WinUI 3),如果这与您的应用模型更匹配。
- 输入选择的项目名称。
- 单击 “创建” 。
安装 Win2D
Win2D 作为 NuGet.org 包发布,需要先安装,然后才能在 WinUI 项目中使用这些效果。
- 转到工具>NuGet 包管理器>管理解决方案的 NuGet 包,然后启动 NuGet 包管理器。
- 搜索 Win2D.WinUI 并为项目安装该包。
- 接受许可协议。
- 单击 “关闭” 。
在接下来的几个步骤中,我们将使用合成 API 将饱和度效果应用于此猫图像,这将删除所有饱和度。 在此模型中,将创建效果,然后应用于图像。
设置合成基础设置
_compositor = ElementCompositionPreview.GetElementVisual(MyHost).Compositor;
_root = _compositor.CreateContainerVisual();
ElementCompositionPreview.SetElementChildVisual(MyHost, _root);
创建 CompositionSurface 笔刷
CompositionSurfaceBrush surfaceBrush = _compositor.CreateSurfaceBrush();
LoadedImageSurface imageSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/cat.png"));
surfaceBrush.Surface = imageSurface;
创建、编译和应用效果
创建图形效果。
var graphicsEffect = new SaturationEffect { Saturation = 0.0f, Source = new CompositionEffectSourceParameter("mySource") };编译效果并创建效果画笔。
var effectFactory = _compositor.CreateEffectFactory(graphicsEffect); var catEffect = effectFactory.CreateBrush(); catEffect.SetSourceParameter("mySource", surfaceBrush);在合成树中创建 SpriteVisual 并应用效果。
var catVisual = _compositor.CreateSpriteVisual(); catVisual.Brush = catEffect; catVisual.Size = new Vector2(219, 300); _root.Children.InsertAtBottom(catVisual);运行应用。 你的结果应该是一只不饱和的猫: