[UWP]CompositionLinearGradientBrush加BlendEffect,双倍的快乐
- 2019 年 10 月 28 日
- 笔记
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