[UWP]抄抄《CSS 故障艺术》的动画
1. 前言
什么是故障艺术(Glitch Art 风)?我们熟知的抖音的 LOGO 正是故障艺术其中一种表现形式。它有一种魔幻的感觉,看起来具有闪烁、震动的效果,很吸引人眼球。故障艺术它模拟了画面信号出现故障导致成像错误的感觉。青色色块与红色色块无法重合就是这种故障的体现。从胶片时代开始到今天的数码时代,这种故障一直是观众非常熟悉的现象。
上个月看到CSS 故障艺术这篇文章,最近想转换心情于是开始抄它的动画了(顺便为博客园的UWP板块吊命)。CSS的mix-blend-mode好像很好用,这次用UWP中Win2D的BlendEffect模仿它的玩法。
2. 什么是BlendEffect
Microsoft.Graphics.Canvas.Effects命名空间下的BlendEffect 用于组合两张图片(分别是作为输入源的Background和Foreground),它包含多种模式,如下图所示:

要使用BlendEffect,需要为它设置Mode,并将Foreground和Background设置为CompositionEffectSourceParameter:
var blendEffect = new BlendEffect()
{
Mode = BlendEffectMode.Screen,
Foreground = new CompositionEffectSourceParameter("Main"),
Background = new CompositionEffectSourceParameter("Tint"),
};
然后使用这个BlendEffect创建Brush,并用SetSourceParameter设置它的Foreground和Background为需要混合的两个CompositionBrush:
var effectFactory = compositor.CreateEffectFactory(blendEffect);
var blendEffectBrush = effectFactory.CreateBrush();
blendEffectBrush.SetSourceParameter("Main", foregroundBrush);
blendEffectBrush.SetSourceParameter("Tint", backgroundBrush);
这样Foreground和Background就会根据Mode指定的模式进行混合。
3. 各种模式下的文字混合效果
CompositionAPI没有提供文字书写的功能,倒是Win2D有提供这个功能,我在用Win2D实现镂空文字有介绍如何使用Win2D创建出一个包含文字的CompositionSurfaceBrush,这次把它重新封装了一下,然后使用下面的代码显示各种模式下的混合效果。
private void AddTextToRoot(BlendEffectMode blendEffectMode)
{
var redBrushWrapper = CreateTextToBrushWrapper(blendEffectMode.ToString(), Colors.Red);
var blueBrushWrapper = CreateTextToBrushWrapper(blendEffectMode.ToString(), Colors.Cyan);
blueBrushWrapper.Brush.Offset = new Vector2(-4f, 0);
var textVisual = Compositor.CreateSpriteVisual();
textVisual.Brush = CreateBrush(blueBrushWrapper.Brush, redBrushWrapper.Brush, blendEffectMode);
textVisual.Size = new Vector2(400, 70);
var background = new Rectangle { Height = 70, Width = 400 };
ElementCompositionPreview.SetElementChildVisual(background, textVisual);
Root.Children.Add(background);
}
private CompositionBrush CreateBrush(CompositionBrush foreground, CompositionBrush background, BlendEffectMode blendEffectMode)
{
var compositor = Window.Current.Compositor;
var effect = new BlendEffect()
{
Mode = blendEffectMode,
Foreground = new CompositionEffectSourceParameter("Main"),
Background = new CompositionEffectSourceParameter("Tint"),
};
var effectFactory = compositor.CreateEffectFactory(effect);
var compositionBrush = effectFactory.CreateBrush();
compositionBrush.SetSourceParameter("Main", foreground);
compositionBrush.SetSourceParameter("Tint", background);
return compositionBrush;
}

上图为各种BlendEffectMode下红色和蓝色文字的混合效果。
4. 图片的 Glitch Art 风
理解BlendEffect的用法和作用后,现在可以做些故障艺术的尝试了。拿下面这张图片来尝试:

private (CompositionBrush compositionBrush, CompositionSurfaceBrush compositionSurfaceBrush) CreateBrush(string imageName, Color color)
{
var compositor = Window.Current.Compositor;
var loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/Images/" + imageName));
var compositionSurfaceBrush = compositor.CreateSurfaceBrush();
compositionSurfaceBrush.Surface = loadedSurface;
var compositionBrush = CreateBrush(compositionSurfaceBrush, compositor.CreateColorBrush(color), BlendEffectMode.Lighten);
return (compositionBrush, compositionSurfaceBrush);
}
使用上面的代码分别将这张图片与从Colors.Red(255,0,0)和Colors.Cyan(0,255,255)创建出来的CompositionColorBrush使用BlendEffectMode.Lighten进行混合,得到下面的效果:

var compositor = Window.Current.Compositor;
var (foreground, foregroundBrush) = CreateBrush(imageName, Colors.Cyan);
var (background, backgroundBrush) = CreateBrush(imageName, Colors.Red);
foregroundBrush.Offset = new Vector2(10, 0);
var brush = CreateBrush(foreground, background, BlendEffectMode.Darken);
使用BlendEffectMode.Darken将两张图片混合,再把其中一张图偏移10像素后,得到如下效果,这样图片的故障艺术分格就完成了:

5. 动态类抖音风格 Glitch 效果
继续抄动画,连标题一起抄。将两个文字的CompositionSurfaceBrush使用BlendEffectMode.Lighten进行混合,然后对它们的Offset做动画:
CreateBrush(backgroundWrapper.Brush, foregroundWrapper.Brush, BlendEffectMode.Lighten);
StartOffsetAnimation(backgroundWrapper.Brush, TimeSpan.FromSeconds(0.95), TimeSpan.Zero);
StartOffsetAnimation(foregroundWrapper.Brush, TimeSpan.FromSeconds(1.1), TimeSpan.FromSeconds(0.2));
private void StartOffsetAnimation(CompositionSurfaceBrush brush, TimeSpan duration, TimeSpan delay)
{
var offsetAnimation = Compositor.CreateVector2KeyFrameAnimation();
offsetAnimation.Duration = duration;
offsetAnimation.DelayTime = delay;
offsetAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
void addKey(float key, float top, float left)
{
offsetAnimation.InsertKeyFrame(key, new Vector2(top * 2.5f, left * 2.5f));
};
addKey(.1f, -0.4f, -1.1f);
addKey(.2f, 0.4f, -0.2f);
addKey(.3f, 0f, .5f);
addKey(.4f, -0.3f, -0.7f);
addKey(.5f, 0, .2f);
addKey(.6f, 1.8f, 1.2f);
addKey(.7f, -1f, .1f);
addKey(.8f, -0.4f, -0.9f);
addKey(.9f, 0, 1.2f);
addKey(1, 0, -1.2f);
brush.StartAnimation(nameof(CompositionSurfaceBrush.Offset), offsetAnimation);
}
再在中间放一条上下移动的黑线,故障的效果就出来了:

6. 更复杂的Glitch效果
这次没法完全抄CSS的动画了,我能力有限,大致抄个意思得了。
创建两个白色黑底带阴影(BlurAmount = 0)的文字(如下所示):

错开几个像素后用BlendEffectMode.Multiply混合在一起,一种更复杂的故障艺术动画就完成了:

再在后面放一个白色的文字,分别调整前面两个文字的高度,效果如下:

然后对前面两个文字的高度进行动画,效果就出来了:
StartHeightAnimation(redBrushWrapper, new List<(double, double)>() { (0, 1), (20, 80), (60, 15), (100, 105) }, TimeSpan.FromSeconds(1), TimeSpan.Zero);
StartHeightAnimation(blueBrushWrapper, new List<(double, double)>() { (0, 110), (20, 112.5), (35, 30), (50, 100), (60, 50), (70, 85), (80, 55), (100, 1) }, TimeSpan.FromSeconds(1.5), TimeSpan.Zero);
private void StartHeightAnimation(TextToBrushWrapper brush, List<(double, double)> keyFrames, TimeSpan duration, TimeSpan delay)
{
var storyboard = new Storyboard();
var animation = new DoubleAnimationUsingKeyFrames();
animation.EnableDependentAnimation = true;
Storyboard.SetTarget(animation, brush);
Storyboard.SetTargetProperty(animation, nameof(TextToBrushWrapper.Height));
foreach (var item in keyFrames)
{
animation.KeyFrames.Add(new LinearDoubleKeyFrame { KeyTime = duration / 100 * item.Item1, Value = item.Item2 });
}
storyboard.Children.Add(animation);
storyboard.RepeatBehavior = RepeatBehavior.Forever;
storyboard.BeginTime = delay;
storyboard.Begin();
}

7. 结语
为了从大佬那里抄动画我还特地新建了一个项目。
原文还有很多动画可以参考,但我半途而废了,搞明白大致的原理后新鲜感就过去了。看起来CPU、GPU的占用也不高,只是暂时想不到有什么实际应用的场景,博客也写了,图片也截了,玩腻就抛弃。
8. 源码
DinoChan_uwp_design_and_animation_lab 一个收集UWP的设计和动画的项目。
[UWP]抄抄《CSS 故障艺术》的动画的更多相关文章
- [UWP]使用AlphaMaskEffect提升故障艺术动画的性能(顺便介绍怎么使用性能探测器分析UWP程序)
前几天发布了抄抄<CSS 故障艺术>的动画这篇文章,在这篇文章里介绍了如何使用Win2D绘制文字然后配合BlendEffect制作故障艺术的动画.本来打算就这样收手不玩这个动画了,但后来又 ...
- CSS 故障艺术
本文的主题是 Glitch Art,故障艺术. 什么是故障艺术?我们熟知的抖音的 LOGO 正是故障艺术其中一种表现形式.它有一种魔幻的感觉,看起来具有闪烁.震动的效果,很吸引人眼球. 故障艺术它模拟 ...
- 抖音抖一抖-SVG和CSS视觉故障艺术小赏
故障艺术,英文名称叫glitch,在很多赛博朋克作品中经常看到,其实就是故意表现一种显示设备的小故障效果,抖音的图标其实就是这种的效果,我们看下这个图标 这个图标中的红色和蓝色的偏移其实就是一种故障艺 ...
- 有趣的 CSS 像素艺术
原文地址:https://css-tricks.com/fun-times-css-pixel-art/#article-header-id-4 译者:nzbin 友情提示:由于国内网络的原因,Cod ...
- css的艺术
鲁先生曾经说过:"html和css都不能算一门语言..." html确实不能算一门语言,他只是二三十个英语单词而已,但是css不一样,css是==艺术== 骚操作 上图的12个图标 ...
- 纯css实现苹果表盘动画
欢迎訪问我们的博客:http://www.w3ctrain.com/2015/07/06/Apple-Watch-Dials/ 随着苹果表的大量生产,我想.用CSS来实现拨号动画的时候到了. 在这篇文 ...
- No.3 - CSS transition 和 CSS transform 配合制作动画
课程概述 作业提交截止时间:09-01 任务目的 深度理解掌握 transition-timing-function 以及它的意义 学会配合使用 CSS transform 和CSS transiti ...
- uwp - 做一个相对炫酷的动画按钮/按钮动画
原文:uwp - 做一个相对炫酷的动画按钮/按钮动画 看腻了系统自带的button animation何不尝试下自定义一个较为炫酷的动画顺便提升用户体验.效果图: 动画分为几个部分,分别是:内圆从中心 ...
- css吃豆人动画
一. Css吃豆人动画 1. 上半圆:两个div,内部一个圆div,外部设置宽高截取半圆 外部div动画:animation: 动画样式 1s(时长) ease(动画先低速后快速) infinite( ...
随机推荐
- 在MVC模式下通过Jqgrid表格操作MongoDB数据
看到下图,是通过Jqgrid实现表格数据的基本增删查改的操作.表格数据增删改是一般企业应用系统开发的常见功能,不过不同的是这个表格数据来源是非关系型的数据库MongoDB.nosql虽然概念新颖,但是 ...
- Java中的字符串比较
在C++中,两个字符串比较的代码可以为: (string1==string2) 但是在java中,这个代码即使在两个字符串完全相同的情况下也会返回 false ,Java中必须使用 string1.e ...
- Java Servlet和Java Filter简介
一:简介servlet 1.什么是Servlet? Servlet可以通过多种方式进行描述,具体取决于上下文: (1)Servlet是一种用于创建web应用程序的技术 (2)Servlet是一个API ...
- for循环的应用
for循环的应用:迭代法,穷举法. 一.迭代法:(有一定规律) 每次循环都是从上次运算结果中获得数据,本次运算的结果都是要为下次运算做准备. 例:1.100以内所有数的和. int sum = 0;f ...
- Python测试开发-创建模态框及保存数据
Python测试开发-创建模态框及保存数据 原创: fin 测试开发社区 前天 什么是模态框? 模态框是指的在覆盖在父窗体上的子窗体.可用来做交互,我们经常会看到模态框用来登录.确定等等,到底是怎 ...
- 【原创】面试官问我G1回收器怎么知道你是什么时候的垃圾?
这是why技术的第36篇原创文章 上面的图片是我上周末在家拍的.以后的文章里面我的第一张配图都用自己随手拍下的照片吧.分享生活,分享技术,哈哈. 阳台上的花开了,成都的春天快来了,疫情也应该快要过去了 ...
- C#连接Informix数据库
最近在工作中遇到了需要连接Informix数据库的问题,在通过研究后发现了可以通过多种方式实现,我选择的是通过IBM Informix .NET Provider.该方式需要引用IBM.Data.In ...
- node.js-web服务器
node.js--web服务器 目前最主流的三个Web服务器是Apache.Nginx.IIS. 使用 Node 创建 Web 服务器 以下是演示一个最基本的 HTTP 服务器架构(使用8081端口) ...
- 大多数项目中会用到的webpack小技巧
原文地址 本文是作者对自己所学的webpack技巧的总结,在没有指定特殊情况下适用于webpack 3.0版本. 进度汇报 使用webpack --progress --colors这样可以让编译的输 ...
- scroll-view组件bindscroll实例应用:自定义滚动条
我们知道scroll-view组件作为滑动控件非常好用,而有时候我们想放置一个跟随滚动位置来跟进的滚动条,但又不想用滚动条api该怎么办呢?(当然是自己写一个呗还能怎么办[自黑冷漠脸])嗯,没错.自己 ...