上一篇文章中我们介绍了Avalonia中CompositionAnimation(合成动画)的使用方法与优势
先前的版本中,合成动画只能在Visual的部分属性上使用。但在Avalonia 12.2中实现了CompositionBrush(合成笔刷),这将允许我们在笔刷上也能使用合成动画,从而更方便地实现一些高级笔刷效果
此功能的实现由我编写,实现细节可以在PR #20181中查看
基本用法
CompositionBrush需要从Compositor中创建。以下代码创建一个纯色合成笔刷:
var compositor = ElementComposition.GetElementVisual(BrushHost)!.Compositor;
var brush = compositor.CreateSolidColorBrush();我们可以创建一个KeyFrameAnimation并在CompositionBrush启动,让这个笔刷的颜色不断改变:
var animation = compositor.CreateColorKeyFrameAnimation();
animation.InsertKeyFrame(0f, Colors.Red);
animation.InsertKeyFrame(0.5f, Colors.Green);
animation.InsertKeyFrame(1f, Colors.Blue);
animation.Duration = TimeSpan.FromSeconds(5);
animation.IterationBehavior = AnimationIterationBehavior.Forever; // 重复播放
animation.Direction = PlaybackDirection.Alternate; // 正向播放完毕后反向播放
brush.StartAnimation("Color", animation);所有CompositionBrush均实现了IBrush接口。因此你可以像普通笔刷一样使用它们:
BrushHost.Background = brush;最终效果如下:
显然,使用
Transitions和Storyboard,或添加一个定时器并不断更新笔刷的颜色,都可以创建相同效果的动画但这两种方法的代码都更加冗长,且性能远不及
CompositionBrush(参考上篇文章介绍CompositionAnimation原理的部分)
示例1:动态发光效果
AI相关的应用中经常能见到这种渐变发光边框,看上去有一种色彩流动的感觉:
通过CreateConicGradientBrush()创建一个圆形渐变并添加相应的渐变色:
因为
GradientStop本身也要支持动画,所以CompositionGradientBrush使用CompositionGradientStop而非Avalonia.Media.GradientStop使用
Compositor.CreateGradientStop()方法来创建它们
var brush = compositor.CreateConicGradientBrush();
brush.GradientStops.Add(compositor.CreateGradientStop(0f, Colors.Cyan));
brush.GradientStops.Add(compositor.CreateGradientStop(0.25f, Colors.Magenta));
brush.GradientStops.Add(compositor.CreateGradientStop(0.5f, Colors.Yellow));
brush.GradientStops.Add(compositor.CreateGradientStop(0.75f, Colors.Lime));
brush.GradientStops.Add(compositor.CreateGradientStop(1f, Colors.Cyan));
brush.Center = RelativePoint.Center;为了达到色彩流动的效果,我们要让这个圆形渐变笔刷“转”起来
因此,我们选择对其Angle属性进行动画:
var animation = compositor.CreateScalarKeyFrameAnimation();
animation.Duration = TimeSpan.FromSeconds(5);
animation.IterationBehavior = AnimationIterationBehavior.Forever;
animation.InsertKeyFrame(0f, 0f);
animation.InsertKeyFrame(1f, 360f);
brush.StartAnimation("Angle", animation);
BrushHost.BorderBrush = brush;现在BrushHost的边框已经有了彩虹跑马灯的样子:
而发光效果可以直接使用XAML搞定,创建一个元素并绑定相同的Brush,应用一下模糊效果即可
<Panel>
<Border
Background="{Binding #BrushHost.BorderBrush}"
Opacity="0.5"
CornerRadius="8">
<Border.Effect>
<BlurEffect Radius="100" />
</Border.Effect>
</Border>
<Border
x:Name="BrushHost"
Background="Gray"
BorderThickness="1"
CornerRadius="8"/>
</Panel>示例2:骨架屏
骨架屏常用于指示加载状态,例如Microsoft Store的加载页面:
先创建一个LinearGradientBrush,通过透明渐变来实现骨架屏的光带效果:
var brush = compositor.CreateLinearGradientBrush();
brush.StartPoint = new RelativePoint(0, 0.5, RelativeUnit.Relative);
brush.EndPoint = new RelativePoint(1, 0.5, RelativeUnit.Relative);
var leadingStop = compositor.CreateGradientStop(0f, Colors.Transparent);
var highlightStop = compositor.CreateGradientStop(
0.15f, Color.FromArgb(96, 255, 255, 255));
var trailingStop = compositor.CreateGradientStop(0.3f, Colors.Transparent);
brush.GradientStops.Add(leadingStop);
brush.GradientStops.Add(highlightStop);
brush.GradientStops.Add(trailingStop);为了让光带移动起来,我们要控制渐变的GradientStop,使其重复从左到右移动:
void AnimateOffset(CompositionGradientStop gradientStop, float from, float to)
{
var animation = compositor.CreateScalarKeyFrameAnimation();
animation.Duration = TimeSpan.FromSeconds(1.5);
animation.IterationBehavior = AnimationIterationBehavior.Forever;
animation.InsertKeyFrame(0f, from);
animation.InsertKeyFrame(1f, to);
gradientStop.StartAnimation("Offset", animation);
}
AnimateOffset(leadingStop, 0f, 0.7f);
AnimateOffset(highlightStop, 0.15f, 0.85f);
AnimateOffset(trailingStop, 0.3f, 1f);
BrushHost.Background = brush;把此使用此笔刷的元素作为光带层,叠在占位符元素上,就能看到一个标准的动态骨架屏效果: