weixin_39880899于 2020-12-11 09:26:23 发布

阅读量521 收藏

点赞数
文章标签: wpf 动画显示隐藏
 

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上写字,这里就不再重复。为了可以为文字添加阴影,需要用到CanvasRenderTargetGaussianBlurEffect

CanvasRenderTarget是一个可以用来画图的渲染目标。实现文字阴影的步骤如下:将文字画到CanvasRenderTarget,然后用它作为GaussianBlurEffect.Source产生一张高斯模糊的图片,这样看上去就和文字的阴影一样。然后再在这张模糊的图片的前面画上原本的文字。

代码如下所示:

  1.  
    using (var session = CanvasComposition.CreateDrawingSession(drawingSurface))
  2.  
    {
  3.  
    session.Clear(Colors.Transparent);
  4.  
    using (var textLayout = new CanvasTextLayout(session, Text, textFormat, width, height))
  5.  
    {
  6.  
    var bitmap = new CanvasRenderTarget(session, width, height);
  7.  
    using (var bitmapSession = bitmap.CreateDrawingSession())
  8.  
    {
  9.  
    bitmapSession.DrawTextLayout(textLayout, 0, 0, FontColor);
  10.  
    }
  11.  
    var blur = new GaussianBlurEffect
  12.  
    {
  13.  
    BlurAmount = (float)BlurAmount,
  14.  
    Source = bitmap,
  15.  
    BorderMode = EffectBorderMode.Hard
  16.  
    };
  17.  
     
  18.  
    session.DrawImage(blur, 0, 0);
  19.  
    session.DrawTextLayout(textLayout, 0, 0, FontColor);
  20.  
    }
  21.  
    }

效果如下(因为我用了白色字体,这时候已经不怎么像阴影了):

关于CavasRenderTaget,死鱼的这篇文章有详细介绍。他的这个专栏的文章都很有趣。

3. 使用CanvasActiveLayer裁剪文字

关于裁剪文字,有几件事需要做。

首先获取需要裁剪的文字的轮廓,这使用上一篇文章介绍过的CanvasGeometry.CreateText就可以了,这个函数的返回值是一个CanvasGeometry。然后使用CanvasGeometry.CreateRectangle获取整个画布的CanvasGeometry,将他们用CombineWith相减得出文字以外的部分,具体代码如下:

  1.  
    var fullSizeGeometry = CanvasGeometry.CreateRectangle(session, 0, 0, width, height);
  2.  
    var textGeometry = CanvasGeometry.CreateText(textLayout);
  3.  
    var finalGeometry = fullSizeGeometry.CombineWith(textGeometry, Matrix3x2.Identity, CanvasGeometryCombine.Exclude);

这里之所以不直接使用textGeometry,是因为我们并不是真的裁剪出文字的部分,而是像WPF的OpacityMask那样用透明度控制显示的部分。CanvasActiveLayer就是用来实现这个功能。CanvasDrawingSession.CreateLayer函数使用透明度和CanvasGeometry创建一个CanvasActiveLayer,在创建Layer后CanvasDrawingSession的操作都会应用这个透明度,直到Layer关闭。

  1.  
    using (var layer = session.CreateLayer(1, finalGeometry))
  2.  
    {
  3.  
    //DrawSth
  4.  
    }

最后效果如下:

关于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。

  1.  
    var maskBrush = Compositor.CreateMaskBrush();
  2.  
    maskBrush.Mask = Compositor.CreateSurfaceBrush(DrawingSurface);
  3.  
    maskBrush.Source = Compositor.CreateLinearGradientBrush();

本来还想做到大紫大红的,但被吐槽和本来低调内敛的目的不符合,所以复用了以前这篇文章的配色,CompositionLinearGradientBrush加BlendEffect做成了有些复杂的配色(但实际上太暗了看不出来):

这时候效果如下:

5. 使用PointLight和AmbientLight制作动画

我在使用PointLight并实现动画效果这篇文章里介绍了PointLight的用法及基本动画,这次豪华些,同时有从左到右的红光以及从右到左的蓝光,这两个PointLight的动画效果大致是这样:

因为PointLight最多只能叠加两个,所以再使用AmbientLight并对它的Intensity属性做动画,这样动画就会变得复杂些,最终实现了文章开头的动画。

  1.  
    var compositor = Window.Current.Compositor;
  2.  
    var ambientLight = compositor.CreateAmbientLight();
  3.  
    ambientLight.Intensity = 0;
  4.  
    ambientLight.Color = Colors.White;
  5.  
     
  6.  
    var intensityAnimation = compositor.CreateScalarKeyFrameAnimation();
  7.  
    intensityAnimation.InsertKeyFrame(0.2f, 0, compositor.CreateLinearEasingFunction());
  8.  
    intensityAnimation.InsertKeyFrame(0.5f, 0.20f, compositor.CreateLinearEasingFunction());
  9.  
    intensityAnimation.InsertKeyFrame(0.8f, 0, compositor.CreateLinearEasingFunction());
  10.  
    intensityAnimation.Duration = TimeSpan.FromSeconds(10);
  11.  
    intensityAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
  12.  
     
  13.  
    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实现文字的发光效果,并制作动画的更多相关文章

  1. [UWP]用Win2D和CompositionAPI实现文字的发光效果,并制作动画

    1. 成果 献祭了周末的晚上,成功召唤出了上面的番茄钟.正当我在感慨"不愧是Shadow大人,这难道就是传说中的五彩斑斓的黑?" "那才不是什么阴影效果,那是发光效果.& ...

  2. js进阶 13-3 jquery动画显示隐藏,滑动,淡入淡出的本质是什么

    js进阶 13-3 jquery动画显示隐藏,滑动,淡入淡出的本质是什么 一.总结 一句话总结:分别改变display,高度,opacity透明度这三种属性. 1.fade系列函数有哪四个? fade ...

  3. 前端制作动画的几种方式(css3,js)

    制作动态的网页是是前端工程师必备的技能,很好的实现动画能够极大的提高用户体验,增强交互效果,那么动画有多少实现方式,一直对此有选择恐惧症的我就总结一下,以便在开发的时候选择最好的实现方式. 1.css ...

  4. canvas学习之制作动画

    html部分 ...... <body> <canvas id="myCanvas" width="400" height="400 ...

  5. ActionBar compat 如何禁用ActionBar的显示/隐藏动画

    ActionBar compat 如何关闭ActionBar的显示隐藏动画 @Override public boolean onCreateOptionsMenu(Menu menu) { //消除 ...

  6. jQuery-4.动画篇---动画基础隐藏和显示

    jQuery中隐藏元素的hide方法 让页面上的元素不可见,一般可以通过设置css的display为none属性.但是通过css直接修改是静态的布局,如果在代码执行的时候,一般是通过js控制元素的st ...

  7. jQuery基础(动画篇 animate,显示隐藏,淡入淡出,下拉切换)

    1.jQuery中隐藏元素的hide方法   让页面上的元素不可见,一般可以通过设置css的display为none属性.但是通过css直接修改是静态的布局,如果在代码执行的时候,一般是通过js控制元 ...

  8. js进阶 13-1 jquery动画中的显示隐藏函数有哪些

    js进阶 13-1 jquery动画中的显示隐藏函数有哪些 一.总结 一句话总结:show(),hide(),toggle(),这三个. 1.jquery动画中显示隐藏效果函数有哪些? show()h ...

  9. jQuery - 02. 样式表属性操作/类操作、动画、显示隐藏、滑入、淡入、停止动画、节点操作、添加对象、清空节点

    样式表属性操作.css $("div").css({'width':100,'height':100,'background':'red'}); $("div" ...

  10. jQuery动画之显示隐藏动画

    1. 显示动画 以下面一个代码示例: <!doctype html> <html lang="en"> <head> <meta char ...

随机推荐

  1. Python 爬虫之 xpath

    0x01 XML 基础 xpath 是在 XML 文档中搜索内容的一门语言 HTML 是 XML 的一个子集 XML 代码举例: <book> <isbn>978xxxxxxx ...

  2. k8s 深入篇———— k8s 的本质[四]

    前言 简单整理一下k8s的本质. 正文 首先,Kubernetes 项目要解决的问题是什么? 编排?调度?容器云?还是集群管理? 实际上,这个问题到目前为止都没有固定的答案.因为在不同的发展阶段,Ku ...

  3. 重新整理 .net core 实践篇—————应用分层[二十四]

    前言 简单整理一下分层. 正文 应用程序分层,分为: 1.领域模型层 2.基础设施层 3.应用层 4.共享层 共享层 共享层一般包括下面几个类库. 有一个Core 的类库,比如说BLog.Core. ...

  4. 什么是ip协议二

    前言 续前面一章. 正文 看下ip选项: 看一张图: 这个ip选项一般我们不用看,即使你去搞硬件,那么做c++或者c的人会告诉你填啥,按照他们设置即可. 那么ip是如何传输的呢? 先看这张图,这张图的 ...

  5. tinyproxy轻量代理服务器安装

    tinyproxy是一款用于POSIX操作系统的轻量级HTTP/HTTPS代理服务程序,非常小巧快速,便于部署,性能也不差,因此适合在嵌入式设备上使用,tinyproxy的仓库和文档链接分别是: 仓库 ...

  6. 【Oracle】列拆行/对多行数据的单行数据进行分割并多行显示

    [Oracle]列拆行/对多行数据的单行数据进行分割并多行显示 参考链接:Oracle 一行字符串拆分为多行_oracle一行拆分成多行-CSDN博客 背景:要对一个表的字段的内容进行分割,分隔符都是 ...

  7. Cube 技术解读 | 详解「支付宝」全新的卡片技术栈

    ​简介: 魔方卡片(Cube),让 App 首页实现敏捷更新. ​ CodeHub#7 正式落幕,来自蚂蚁集团的技术专家「京君」与掘金社区的开发者们分享了「支付宝」全新的卡片技术栈--魔方卡片(Cub ...

  8. 外部工具连接SaaS模式云数据仓库MaxCompute实战——商业BI分析工具篇

    简介: MaxCompute 是面向分析的企业级 SaaS 模式云数据仓库,以 Serverless 架构提供快速.全托管的在线数据仓库服务,消除了传统数据平台在资源扩展性和弹性方面的限制,最小化用户 ...

  9. [FAQ] Pytorch PytorchStreamReader failed reading zip archive

    比如:rm -rf ~/.cache/huggingface Tool:ChatAI Link:https://www.cnblogs.com/farwish/p/17290240.html

  10. K8s集群中部署SpringCloud在线购物平台(二)

    三.harbor简介 harbor 是私有镜像仓库,用来存储和分发镜像的 docker 还有一个官方的镜像仓库 docker hub,免费用户只能简单的使用,创建一个私有镜像仓库,存储 镜像,付费用户 ...