[UWP]组合CompositionBrush并使用BlendEffect
1. 什么是BlendEffect
上一篇文章介绍了CompositionLinearGradientBrush的基本用法, 这篇文章再结合BlendEffec介绍一些更复杂的玩法。
Microsoft.Graphics.Canvas.Effects命名空间下的BlendEffect 用于组合两张图片(分别是作为输入源的Background和Foreground),它包含多种模式,如下图所示:

其中最简单的是Screen模式,它的计算公式如下

看起来有点复杂, 我的理解是它相当于色轮中Background和Foreground之间拉直线,在直线的中间点的颜色,如下面这张图,红色和蓝色组合成为紫色:

2. 组合CompositionBrush并使用BlendEffect
许多 CompositionBrushes 使用其他 CompositionBrushes 作为输入。 例如,使用 SetSourceParameter 方法可以将其他 CompositionBrush 设为 CompositionEffectBrush 的输入。这是CompositionBrush最好玩的地方之一。下面的例子介绍了怎么使用BlendEffect创建CompositionBrush。
首先创建两个CompositionLinearGradientBrush:
var foregroundBrush = compositor.CreateLinearGradientBrush();
foregroundBrush.StartPoint = Vector2.Zero;
foregroundBrush.EndPoint = new Vector2(1.0f);
var redGradientStop = compositor.CreateColorGradientStop();
redGradientStop.Offset = 0f;
redGradientStop.Color = Color.FromArgb(255, 255, 0, 0);
var yellowGradientStop = compositor.CreateColorGradientStop();
yellowGradientStop.Offset = 1f;
yellowGradientStop.Color = Color.FromArgb(255, 0, 178, 255);
foregroundBrush.ColorStops.Add(redGradientStop);
foregroundBrush.ColorStops.Add(yellowGradientStop);
var backgroundBrush = compositor.CreateLinearGradientBrush();
backgroundBrush.StartPoint = new Vector2(0, 1f);
backgroundBrush.EndPoint = new Vector2(1f, 0);
var blueGradientStop = compositor.CreateColorGradientStop();
blueGradientStop.Offset = 0f;
blueGradientStop.Color = Color.FromArgb(255, 0, 0, 255);
var greenGradientStop = compositor.CreateColorGradientStop();
greenGradientStop.Offset = 1f;
greenGradientStop.Color = Color.FromArgb(255, 0, 255, 0);
backgroundBrush.ColorStops.Add(blueGradientStop);
backgroundBrush.ColorStops.Add(greenGradientStop);
它们的效果分别如下面两张图片所示:


接下来创建BlendEffect,并将Foreground和Background设置为CompositionEffectSourceParameter
var blendEffect = new BlendEffect()
{
Mode = BlendEffectMode.Screen,
Foreground = new CompositionEffectSourceParameter("Main"),
Background = new CompositionEffectSourceParameter("Tint"),
};
使用BlendEffect创建Brush,并用SetSourceParameter设置它的Foreground和Background。
var effectFactory = compositor.CreateEffectFactory(blendEffect);
var blendEffectBrush = effectFactory.CreateBrush();
blendEffectBrush.SetSourceParameter("Main", foregroundBrush);
blendEffectBrush.SetSourceParameter("Tint", backgroundBrush);
最后就是一般的使用这个blendEffectBrush的代码:
//创建SpriteVisual并设置Brush
var spriteVisual = compositor.CreateSpriteVisual();
spriteVisual.Brush = blendEffectBrush;
//将自定义 SpriteVisual 设置为元素的可视化树的最后一个子元素。
ElementCompositionPreview.SetElementChildVisual(Gradient, spriteVisual);
最终运行效果如下:

3. 创建动画
和上一篇文章一样,我也把这篇文章用到的技术用在了一个番茄钟应用里,,简单地使用ColorKeyFrameAnimation和ScalarKeyFrameAnimation制作动画:
private void StartOffsetAnimation(CompositionColorGradientStop gradientOffset, float offset)
{
var offsetAnimation = _compositor.CreateScalarKeyFrameAnimation();
offsetAnimation.Duration = TimeSpan.FromSeconds(1);
offsetAnimation.InsertKeyFrame(1.0f, offset);
gradientOffset.StartAnimation(nameof(CompositionColorGradientStop.Offset), offsetAnimation);
}
private void StartColorAnimation(CompositionColorGradientStop gradientOffset, Color color)
{
var colorAnimation = _compositor.CreateColorKeyFrameAnimation();
colorAnimation.Duration = TimeSpan.FromSeconds(2);
colorAnimation.Direction = Windows.UI.Composition.AnimationDirection.Alternate;
colorAnimation.InsertKeyFrame(1.0f, color);
gradientOffset.StartAnimation(nameof(CompositionColorGradientStop.Color), colorAnimation);
}
完整代码在这里,具体运行效果如下:

4. 结语
上面的动画可以安装我的番茄钟应用试玩一下,安装地址:
这篇文章的动画和代码都参考了JustinLiu的代码,感谢他的分享。
使用XAML画笔难以做到这种多向渐变的效果,这都多亏了UWP提供了BlendEffect这个好玩的东西。BlendEffect还有很多其它好玩的模式,大家有空可以多多尝试。
参考
合成画笔 - Windows UWP applications _ Microsoft Docs
源码
OnePomodoro_GradientsWithBlend.xaml.cs at master
[UWP]组合CompositionBrush并使用BlendEffect的更多相关文章
- [UWP]CompositionLinearGradientBrush加BlendEffect,双倍的快乐
原文:[UWP]CompositionLinearGradientBrush加BlendEffect,双倍的快乐 1. 什么是BlendEffect# 上一篇文章介绍了CompositionLinea ...
- UWP 响应键盘组合快捷键
方法1:响应Ctrl+?快捷键 首先在load事件或者keydown事件内注册事件 public MainPage() { this.InitializeComponent(); // Registe ...
- [UWP]用Win2D和CompositionAPI实现文字的发光效果,并制作动画
1. 成果 献祭了周末的晚上,成功召唤出了上面的番茄钟.正当我在感慨"不愧是Shadow大人,这难道就是传说中的五彩斑斓的黑?" "那才不是什么阴影效果,那是发光效果.& ...
- [UWP]抄抄《CSS 故障艺术》的动画
1. 前言 什么是故障艺术(Glitch Art 风)?我们熟知的抖音的 LOGO 正是故障艺术其中一种表现形式.它有一种魔幻的感觉,看起来具有闪烁.震动的效果,很吸引人眼球.故障艺术它模拟了画面信号 ...
- New UWP Community Toolkit - XAML Brushes
概述 上一篇 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾.接下来会针对每个重要更新,结合 SDK 源代码和调用代码详细讲解. 本篇我们 ...
- [UWP]使用AlphaMaskEffect提升故障艺术动画的性能(顺便介绍怎么使用性能探测器分析UWP程序)
前几天发布了抄抄<CSS 故障艺术>的动画这篇文章,在这篇文章里介绍了如何使用Win2D绘制文字然后配合BlendEffect制作故障艺术的动画.本来打算就这样收手不玩这个动画了,但后来又 ...
- MVVM框架从WPF移植到UWP遇到的问题和解决方法
MVVM框架从WPF移植到UWP遇到的问题和解决方法 0x00 起因 这几天开始学习UWP了,之前有WPF经验,所以总体感觉还可以,看了一些基础概念和主题,写了几个测试程序,突然想起来了前一段时间在W ...
- UWP简单示例(三):快速开发2D游戏引擎
准备 IDE:VisualStudio 2015 Language:VB.NET/C# 图形API:Win2D MSDN教程:UWP游戏开发 游戏开发涉及哪些技术? 游戏开发是一门复杂的艺术,编码方面 ...
- 【uwp】浅谈China Daily 中划词翻译的实现
学习uwp开发也有一段时间了,最近上架了一个小应用(China Daily),现在准备将开发中所学到的一些东西拿出来跟大家分享交流一下. 先给出应用的下载链接:China Daily , 感兴趣的童鞋 ...
随机推荐
- 如何从请求、传输、渲染3个方面提升Web前端性能
什么是WEB前端呢?就是用户电脑的浏览器所做的一切事情.我们来看看用户访问网站,浏览器都做了哪些事情: 输入网址 –> 解析域名 -> 请求页面 -> 解析页面并发送页面中的资源请求 ...
- JS替换字符串多余的空格符
var str = 'sdfsdfds '; str.replace(/(^\s*)|(\s*$)/g, "");
- 自定义 Alamofire 的 response serializer
Alamofire 的 DataRequest 类针对二进制数据.字符串.json.属性列表提供了一系列方便解析的方法(内部实际上使用的是 Response Serializer),现在我们要针对服务 ...
- C++ 生成随机数 srand()和rand()
1. rand() rand(产生随机数)表头文件: #include<stdlib.h>定义函数 :int rand(void) 函数说明 :因为rand() 的内部实现是用线性同余法做 ...
- .NET生成漂亮桌面背景
.NET生成漂亮桌面背景 一天,我朋友指着某某付费软件对我说,这个东西不错,每天生成一张桌面背景,还能学英语(放置名人名言和翻译)!我说,这东西搞不好我也能做,然后朋友说,"如果你搞出来了, ...
- redis分布式锁-基本概念与实现方式对比
1.redis中使用WATCH实现锁机制,是最次之的方式.WATCH只会在数据被其他客户端抢先修改了的情况下,“通知”执行了这个命令的客户端,而不会阻止其他客户端对数据进行修改.此类锁成为“乐观锁” ...
- vs code编码设置
在使用vs code(版本1.35.0)打开文件时,出现乱码问题,可通过如下方式设置: 1.针对单个文件 点击右下角的编码按钮(图中为UTF-8),然后选择操作,通过编码重新打开(Reopen wit ...
- IPv6系列-彻底弄明白有状态与无状态配置IPv6地址
深入研究自动分配IPv6地址的Stateless(无状态)与Stateful(有状态)方式 小慢哥的原创文章,欢迎转载 目录 ▪ 一. Link-Local Address的生成方式 ▪ 二. Glo ...
- ouc_software第一次作业:OUC二手物品交易
一.前言 1.项目名称:ouc二手物品交易 2.项目简介 (1)创办一个网上校内二手物品交易平台,供校内师生进行交易二手物品. (2)经过身份认证的用户,可将自己想要交易的二手物品发布至平台,供其他用 ...
- linux 更改文件所属用户及用户组
在Linux中,创建一个文件时,该文件的拥有者都是创建该文件的用户.该文件用户可以修改该文件的拥有者及用户组,当然root用户可以修改任何文件的拥有者及用户组.在Linux中,对于文件的权限(rw ...