wpf 动画显示隐藏_[UWP]用Win2D和CompositionAPI实现文字的发光效果,并制作动画
1. 成果
献祭了周末的晚上,成功召唤出了上面的番茄钟。正当我在感慨“不愧是Shadow大人,这难道就是传说中的五彩斑斓的黑?”
“那才不是什么阴影效果,那是发光效果。”被路过的老婆吐槽了。
系系系,老婆说的都系对的。我还以为我在做阴影动画,现在只好改博客标题了?
要实现上面的动画效果,首先使用CompositionDrawingSurface,在它上面用DrawTextLayout画出文字,然后用GaussianBlurEffect模仿成阴影,然后用CanvasActiveLayer裁剪文字的轮廓,然后用这个CompositionDrawingSurface创建出CompositionSurfaceBrush,然后创建一个CompositionMaskBrush,将CompositionSurfaceBrush作为它的Mask,然后用CompositionLinearGradientBrush创建出渐变,再用BlendEffect将它变成四向渐变,再用ColorKeyFrameAnimation和ScalarKeyFrameAnimation在它上面做动画并把它作为CompositionMaskBrush的Source,然后创建SpriteVisual将CompositionMaskBrush应用上去,然后使用两个PointLight分别从左到右和从右到左照射这个SpriteVisual,再创建一个AmbientLight模仿呼吸灯。
仔细想想……好吧,老婆说得对,我还真的没有用到任何Shadow的Api,这里和Shadow大人半毛钱关系都没有。
这个番茄钟源码可以在这里查看:
OnePomodoro_ShadowTextView.xaml at master
也可以安装我的番茄钟应用试玩一下,安装地址:
一个番茄钟
这篇文章将介绍其中几个关键技术。
2. 使用GaussianBlurEffect模仿阴影
上一篇文章已经介绍过怎么在CompositionDrawingSurface
上写字,这里就不再重复。为了可以为文字添加阴影,需要用到CanvasRenderTarget
和GaussianBlurEffect
。
CanvasRenderTarget是一个可以用来画图的渲染目标。实现文字阴影的步骤如下:将文字画到CanvasRenderTarget,然后用它作为GaussianBlurEffect.Source产生一张高斯模糊的图片,这样看上去就和文字的阴影一样。然后再在这张模糊的图片的前面画上原本的文字。
代码如下所示:
- using (var session = CanvasComposition.CreateDrawingSession(drawingSurface))
- {
- session.Clear(Colors.Transparent);
- using (var textLayout = new CanvasTextLayout(session, Text, textFormat, width, height))
- {
- var bitmap = new CanvasRenderTarget(session, width, height);
- using (var bitmapSession = bitmap.CreateDrawingSession())
- {
- bitmapSession.DrawTextLayout(textLayout, 0, 0, FontColor);
- }
- var blur = new GaussianBlurEffect
- {
- BlurAmount = (float)BlurAmount,
- Source = bitmap,
- BorderMode = EffectBorderMode.Hard
- };
- session.DrawImage(blur, 0, 0);
- session.DrawTextLayout(textLayout, 0, 0, FontColor);
- }
- }
效果如下(因为我用了白色字体,这时候已经不怎么像阴影了):
关于CavasRenderTaget,死鱼的这篇文章有详细介绍。他的这个专栏的文章都很有趣。
3. 使用CanvasActiveLayer裁剪文字
关于裁剪文字,有几件事需要做。
首先获取需要裁剪的文字的轮廓,这使用上一篇文章介绍过的CanvasGeometry.CreateText
就可以了,这个函数的返回值是一个CanvasGeometry。然后使用CanvasGeometry.CreateRectangle
获取整个画布的CanvasGeometry,将他们用CombineWith相减得出文字以外的部分,具体代码如下:
- var fullSizeGeometry = CanvasGeometry.CreateRectangle(session, 0, 0, width, height);
- var textGeometry = CanvasGeometry.CreateText(textLayout);
- var finalGeometry = fullSizeGeometry.CombineWith(textGeometry, Matrix3x2.Identity, CanvasGeometryCombine.Exclude);
这里之所以不直接使用textGeometry,是因为我们并不是真的裁剪出文字的部分,而是像WPF的OpacityMask那样用透明度控制显示的部分。CanvasActiveLayer就是用来实现这个功能。CanvasDrawingSession.CreateLayer
函数使用透明度和CanvasGeometry创建一个CanvasActiveLayer
,在创建Layer后CanvasDrawingSession
的操作都会应用这个透明度,直到Layer关闭。
- using (var layer = session.CreateLayer(1, finalGeometry))
- {
- //DrawSth
- }
最后效果如下:
关于CanvasActiveLayer的更多用法, 可以参考Lindexi的这篇文章。
4. 制作有复杂颜色的阴影
如上图所示,UWP中的DropShadow的Color只能有一种颜色,所以DropShadow不能使用复杂的颜色。这时候就要用到CompositionMaskBrush,CompositionMaskBrush有两个主要属性:Mask和Source。其中Mask是一个CompositionBrush
类型的属性,它指定不透明的蒙板源。简单来说,CompositionMaskBrush的形状就是它的Mask的形状。而Source属性则是它的颜色,这个属性可以是 CompositionColorBrush、CompositionLinearGradientBrush、CompositionSurfaceBrush、CompositionEffectBrush 或 CompositionNineGridBrush 类型的任何 CompositionBrush。可以使用前面创建的CompositionDrawingSurface创建出CompositionSurfaceBrush,最后创建一个CompositionMaskBrush,将CompositionSurfaceBrush作为它的Mask。
- var maskBrush = Compositor.CreateMaskBrush();
- maskBrush.Mask = Compositor.CreateSurfaceBrush(DrawingSurface);
- maskBrush.Source = Compositor.CreateLinearGradientBrush();
本来还想做到大紫大红的,但被吐槽和本来低调内敛的目的不符合,所以复用了以前这篇文章的配色,CompositionLinearGradientBrush加BlendEffect做成了有些复杂的配色(但实际上太暗了看不出来):
这时候效果如下:
5. 使用PointLight和AmbientLight制作动画
我在使用PointLight并实现动画效果这篇文章里介绍了PointLight的用法及基本动画,这次豪华些,同时有从左到右的红光以及从右到左的蓝光,这两个PointLight的动画效果大致是这样:
因为PointLight最多只能叠加两个,所以再使用AmbientLight
并对它的Intensity
属性做动画,这样动画就会变得复杂些,最终实现了文章开头的动画。
- var compositor = Window.Current.Compositor;
- var ambientLight = compositor.CreateAmbientLight();
- ambientLight.Intensity = 0;
- ambientLight.Color = Colors.White;
- var intensityAnimation = compositor.CreateScalarKeyFrameAnimation();
- intensityAnimation.InsertKeyFrame(0.2f, 0, compositor.CreateLinearEasingFunction());
- intensityAnimation.InsertKeyFrame(0.5f, 0.20f, compositor.CreateLinearEasingFunction());
- intensityAnimation.InsertKeyFrame(0.8f, 0, compositor.CreateLinearEasingFunction());
- intensityAnimation.Duration = TimeSpan.FromSeconds(10);
- intensityAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
- ambientLight.StartAnimation(nameof(AmbientLight.Intensity), intensityAnimation);
6. 参考
CanvasRenderTarget Class
CanvasGeometry Class
CanvasActiveLayer Class
CompositionMaskBrush Class (Windows.UI.Composition) - Windows UWP applications _ Microsoft Docs
组合照明 - Windows UWP applications Microsoft Docs
Win2D - 知乎
wpf 动画显示隐藏_[UWP]用Win2D和CompositionAPI实现文字的发光效果,并制作动画的更多相关文章
- [UWP]用Win2D和CompositionAPI实现文字的发光效果,并制作动画
1. 成果 献祭了周末的晚上,成功召唤出了上面的番茄钟.正当我在感慨"不愧是Shadow大人,这难道就是传说中的五彩斑斓的黑?" "那才不是什么阴影效果,那是发光效果.& ...
- js进阶 13-3 jquery动画显示隐藏,滑动,淡入淡出的本质是什么
js进阶 13-3 jquery动画显示隐藏,滑动,淡入淡出的本质是什么 一.总结 一句话总结:分别改变display,高度,opacity透明度这三种属性. 1.fade系列函数有哪四个? fade ...
- 前端制作动画的几种方式(css3,js)
制作动态的网页是是前端工程师必备的技能,很好的实现动画能够极大的提高用户体验,增强交互效果,那么动画有多少实现方式,一直对此有选择恐惧症的我就总结一下,以便在开发的时候选择最好的实现方式. 1.css ...
- canvas学习之制作动画
html部分 ...... <body> <canvas id="myCanvas" width="400" height="400 ...
- ActionBar compat 如何禁用ActionBar的显示/隐藏动画
ActionBar compat 如何关闭ActionBar的显示隐藏动画 @Override public boolean onCreateOptionsMenu(Menu menu) { //消除 ...
- jQuery-4.动画篇---动画基础隐藏和显示
jQuery中隐藏元素的hide方法 让页面上的元素不可见,一般可以通过设置css的display为none属性.但是通过css直接修改是静态的布局,如果在代码执行的时候,一般是通过js控制元素的st ...
- jQuery基础(动画篇 animate,显示隐藏,淡入淡出,下拉切换)
1.jQuery中隐藏元素的hide方法 让页面上的元素不可见,一般可以通过设置css的display为none属性.但是通过css直接修改是静态的布局,如果在代码执行的时候,一般是通过js控制元 ...
- js进阶 13-1 jquery动画中的显示隐藏函数有哪些
js进阶 13-1 jquery动画中的显示隐藏函数有哪些 一.总结 一句话总结:show(),hide(),toggle(),这三个. 1.jquery动画中显示隐藏效果函数有哪些? show()h ...
- jQuery - 02. 样式表属性操作/类操作、动画、显示隐藏、滑入、淡入、停止动画、节点操作、添加对象、清空节点
样式表属性操作.css $("div").css({'width':100,'height':100,'background':'red'}); $("div" ...
- jQuery动画之显示隐藏动画
1. 显示动画 以下面一个代码示例: <!doctype html> <html lang="en"> <head> <meta char ...
随机推荐
- 黑客终端qsnctfwp
进入网页,发现是网页版的 cmd (/doge) 输入ls发现输出了以下内容 按 F12 检查代码,在<script>中发现输入命令为cat /flag则可获得 flag 此时即可直接复制 ...
- redis 简单整理——内存的优化[二十七]
前言 简单介绍一下内存的优化. 正文 Redis所有的数据都在内存中,而内存又是非常宝贵的资源.如何优化内存的使用一直是Redis用户非常关注的问题.本节深入到Redis细节中,探索内存优化的技巧. ...
- Pytorch-卷积神经网络CNN之ResNet的Pytorch代码实现
先说一个小知识,助于理解代码中各个层之间维度是怎么变换的. 卷积函数:一般只用来改变输入数据的维度,例如3维到16维. Conv2d() Conv2d(in_channels:int,out_chan ...
- Django框架——图书管理系统、聚合查询、分组查询、F与Q查询
图书管理系统 1.表设计 先考虑普通字段再考虑外键字段 数据库迁移.测试数据录入 2.首页展示 3.书籍展示 4.书籍添加 5.书籍编辑 后端如何获取用户想要编辑的数据.前端如何展示出待编辑的数据 6 ...
- NOIP模拟四
NOIP模拟四 number 题目描述 现有 \(2^n\) 个点,点编号为 \(0\sim2^n-1\). 定义这些点的一张异或图为: 先选定一个集合 \(S\). 对于原图上编号为 \(x\) 和 ...
- HarmonyOS NEXT应用开发案例——全屏登录页面
全屏登录页面 介绍 本例介绍各种应用登录页面. 全屏登录页面:在主页面点击跳转到全屏登录页后,显示全屏模态页面,全屏模态页面从下方滑出并覆盖整个屏幕,模态页面内容自定义,此处分为默认一键登录方式和其他 ...
- SysOM 案例解析:消失的内存都去哪了 !| 龙蜥技术
简介: 这儿有一份"关于内存不足"排查实例,请查收. 文/系统运维 SIG 在<AK47 所向披靡,内存泄漏一网打尽>一文中,我们分享了slab 内存泄漏的排查方式和工 ...
- 阿里云CDN产品经理陈章炜:边缘创新技术和落地实践
简介: CDN除了加速外,不断被赋予更多价值.在阿里云CDN推出的<极速奔跑吧 2021>首场直播中,阿里云架构师和产品经理不仅对近期阿里云发布的CDN产品最佳实践图进行了详细解读,还对C ...
- dotnet 7 已知问题 WPF 的 TreeView 开启虚拟化之后只显示首项
本文记录 WPF 在 dotnet 7 的一个已知问题,此问题当前已修复,只需更新 SDK 或运行时即可.使用 TreeView 在开启虚拟化之后只显示首项,其他项不显示.本文将告诉大家此问题的原因和 ...
- dotnet 在 UOS 国产系统上使用 MonoDevelop 创建 GTK 全平台带界面应用
本文告诉大家如何在 UOS 国产系统上开始使用 MonoDevelop 开发,通过创建 GTK# 应用,进入界面开发的第一步 在开始之前需要小伙伴先安装好 MonoDevelop 工具 安装完成之后, ...