首页 > 其他分享 >wpf 动画显示隐藏_[UWP]用Win2D和CompositionAPI实现文字的发光效果,并制作动画

wpf 动画显示隐藏_[UWP]用Win2D和CompositionAPI实现文字的发光效果,并制作动画

时间:2024-05-22 23:08:55浏览次数:23  
标签:文字 动画 Win2D CanvasGeometry UWP session var CompositionMaskBrush

于 2020-12-11 09:26:23 发布 阅读量521 收藏 点赞数 文章标签: wpf 动画显示隐藏  

 

9f74723b589728096190b804ab25a259.png

1. 成果

 

53846b17efa304362d650e19c8bb23a3.gif

献祭了周末的晚上,成功召唤出了上面的番茄钟。正当我在感慨“不愧是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.   }

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

 

8f7eeb82929a3e92da72b2ee09e0eef4.png
关于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.   }

最后效果如下:

 

ca4d792d93ddc9482929389469cbf389.png
关于CanvasActiveLayer的更多用法, 可以参考Lindexi的这篇文章。

4. 制作有复杂颜色的阴影

 

41de61502766ebc488b5ebd5aad41a48.png

如上图所示,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做成了有些复杂的配色(但实际上太暗了看不出来):

 

13347e54369c3a617b1e05e0e0827288.png

这时候效果如下:

 

1b7629d12ad50430d0835f798d19e0f2.png

5. 使用PointLight和AmbientLight制作动画

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

 

b4314e916cc855d671d844858f9cbb2b.gif

因为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演示实现发光的字体和模糊按钮_wpf字体发光资源-CSDN文库

标签:文字,动画,Win2D,CanvasGeometry,UWP,session,var,CompositionMaskBrush
From: https://www.cnblogs.com/webenh/p/18207324

相关文章

  • WPF炫酷UI及动画
        偶然看见了一张图,感觉挺好看的,花了点时间将他转化成了我代码仓库的一部分。虽然不难但也费时间。其中除了背景是百度的一张底图,其他所有内容均通过WPF的Path、Line、TextBlock、Border以及DoubleAnimation来实现。效果如下:​纯黑色背景也还蛮好看的。​   ......
  • unity中animator中Trigger多次触发动画的解决方法(基于 stateInfo和ResetTrigger)
    巧妙地重置動畫控制器觸發(ResetTriggers)_哔哩哔哩_bilibili提出了FSMCleaSignals,会在进和出动画时使相关的trigger变为非激活状态,但是当该动作涉及多layer/多trigger控制时,会在该layer中动作未完成时,其他layer读取到了还未更改的异常激活状态的trigger,从而出错,这种错误主要是......
  • Qt QMovie无法显示gif动画的一种解决方法
    注:本来用这种方法显示gif动画是没有问题的。问题:如下方法,槽函数startGif()如下,点击按钮无法出现gif动画分析:gif动画资源确实是加载进来了,但是在执行movie.start()时,整个资源就已经消失了,所以无法显示动画。要使资源长期存在需要用到c中的修饰符: static。1voidshowGif::st......
  • Qt 动画播放之QMovie类
    主要是用到QMovie类实现在事件触发时开启动画播放效果(需要注意的是,这个动画播放默认是循环播放的,如果不做特殊处理动画会一直播放)1QMovie*movie=newQMovie("aaa.gif");2ui->movieLabel->setMovie(movie);3movie->start();//启动gif图片4//movie->......
  • Qt 程序启动画面QSplashScreen
    QSplashScreen是Qt框架提供的一个类,用于在应用程序启动时显示一个带有文本和图像的启动画面(SplashScreen)。使用QSplashScreen类,你可以在应用程序启动时显示一个自定义的启动画面,以提供更好的用户体验。这个类提供了一些方法和属性,可以让你设置启动画面的文本、图像和其......
  • vue之移动端的页面在返回时记住操作的位置,提供滑动动画效果
    1、在main.js中添加importctpRouterfrom'@/ares-ui-extend/CtpRouter';Vue.use(ctpRouter,router);2、添加相应的代码在src的目录下添加 ares-ui-extend的文件夹 ares-ui-extend文件夹的下面添加CtpRouter,CtpRouter下面为: ctp-router.css内容为:/*动画样式*......
  • jQuery2-动画技术入门指南-全-
    jQuery2动画技术入门指南(全)原文:zh.annas-archive.org/md5/71BE345FA56C4A075E859338F3DCA6DA译者:飞龙协议:CCBY-NC-SA4.0序言jQuery是一个跨浏览器的JavaScript库,旨在简化HTML的客户端脚本编写,并且是当今最流行的JavaScript库。利用jQuery提供的功能,开发人员能......
  • 博客园美化:给网页加上loading动画
    先看看效果图:效果还不错吧~......
  • flutter动画— —Hero +photo_view 实现微信朋友圈图片预览
    photo_view预览单张图片依赖photo_view:^0.14.0#微信图片单张图片的预览//PhotoView(//imageProvider://NetworkImage(widget.arguments["imageUrl"]),//)classHeroPageextendsStatefulWidget{finalMaparguments;constHeroPage({super.key,req......
  • flutter动画— —Hero 动画
    Hero动画Hero动画的使用微信朋友圈点击小图片的时候会有一个动画效果到大图预览,这个动画效果就可以使用Hero动画实现。Hero指的是可以在路由(页面)之间“飞行”的widget,简单来说Hero动画就是在路由切换时,有一个共享的widget可以在新旧路由间切换。 页面跳转......