1. 前言

之前用PointLight做了一个番茄钟,效果还不错,具体可见这篇文章:

[UWP]使用PointLight并实现动画效果

后来试玩了Win2D,这次就用Win2D实现文字的镂空效果,配合PointLight做一个内敛不张扬的番茄钟。

实现镂空文字的核心思想是使用CanvasGeometry.CreateText从TextLayout获取一个Geometry,然后使用DrawGeometry将它画到DrawingSurface。这篇文章介绍了具体的实现步骤。

2. 参考例子

Win2D Gallery提供了大量Win2D的Sample,这次就参考了其中的文字镂空效果例子,地址和运行效果如下:

https://github.com/microsoft/Win2D-Samples/blob/master/ExampleGallery/TextOutlines.xaml.cs

3. 实现步骤

Sample的代码量虽多,其实核心并不复杂,下面讲讲需要用到的API:

3.1 CanvasDevice.GetSharedDevice

因为要用到Win2D,所以首先要引用Win2D.uwp nuget包。因为我的目标不是输出到CanvasControl上,而是想要输出到一个SpriteVisual上,所以使用CanvasDevice

  1. var canvasDevice = CanvasDevice.GetSharedDevice();

3.2 CanvasComposition.CreateCompositionGraphicsDevice

然后创建一个Compositor,并将这个Compositor和CanvasDevice关联起来,这里需要使用 CanvasComposition 创建 GraphicsDevice

  1. var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
  2. var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, canvasDevice);

3.3 CompositionGraphicsDevice.CreateDrawingSurface

然后使用CompositionGraphicsDevice.CreateDrawingSurface创建一个CompositionDrawingSurface对象,它是用来绘画内容的表面:

  1. var drawingSurface = graphicsDevice.CreateDrawingSurface(e.NewSize, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);

3.4 Compositor.CreateSurfaceBrush

使用Compositor.CreateSurfaceBrush创建一个CompositionSurfaceBrush,它的作用是使用像素绘制SpriteVisual,简单来说它就是一张位图,然后输出到SpriteVisual上:

  1. var maskSurfaceBrush = compositor.CreateSurfaceBrush(drawingSurface);
  2. spriteTextVisual.Brush = maskSurfaceBrush;

3.5 CanvasComposition.CreateDrawingSession

有了CompositionDrawingSurface就可以为所欲为了,将这个DrawingSurface作为参数,调用CanvasComposition.CreateDrawingSession创建DrawingSession,DrawingSession提供了多个函数,可以自由地在DrawingSurface上画文字、形状、图片甚至SVG。

  1. using (var session = CanvasComposition.CreateDrawingSession(drawingSurface))
  2. {
  3. }

3.6 CanvasTextFormat和CanvasTextLayout

要再DrawingSurface上写字,需要CanvasTextLayout,而CanvasTextLayout中的文字大小、格式等则由CanvasTextFormat定义:

  1. using (var textFormat = new CanvasTextFormat()
  2. {
  3. FontSize = (float)FontSize,
  4. Direction = CanvasTextDirection.LeftToRightThenTopToBottom,
  5. VerticalAlignment = CanvasVerticalAlignment.Center,
  6. HorizontalAlignment = CanvasHorizontalAlignment.Center,
  7. })
  8. {
  9. using (var textLayout = new CanvasTextLayout(session, Text, textFormat, width, height))
  10. {
  11. Color fontColor = FontColor;
  12. session.DrawTextLayout(textLayout, 0, 0, fontColor);
  13. }
  14. }

3.7 CanvasGeometry.CreateText

因为我的目标是镂空的文字,所以不能直接使用DrawTextLayout。这里需要使用CanvasGeometry.CreateText从TextLayout获取一个Geometry,然后使用DrawGeometry将它画到DrawingSurface。CanvasStrokeStyle是可选的,它控制边框的虚线。

  1. using (var textGeometry = CanvasGeometry.CreateText(textLayout))
  2. {
  3. var dashedStroke = new CanvasStrokeStyle()
  4. {
  5. DashStyle = DashStyle
  6. };
  7. session.DrawGeometry(textGeometry, OutlineColor, (float)StrokeWidth, dashedStroke);
  8. }

4. 封装为控件

将上面的代码总结一下,封装为一个OutlineTextControl 控件,它提供了Text、OutlineColor、FontColor等属性,在控件SizeChanged时,或者各个属性改变时调用DrawText重新在CompositionDrawingSurface上绘制文字。代码大致如下:

  1. public class OutlineTextControl : Control
  2. {
  3. private CompositionDrawingSurface _drawingSurface;
  4. public OutlineTextControl()
  5. {
  6. var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
  7. var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, CanvasDevice.GetSharedDevice());
  8. var spriteTextVisual = compositor.CreateSpriteVisual();
  9. ElementCompositionPreview.SetElementChildVisual(this, spriteTextVisual);
  10. SizeChanged += (s, e) =>
  11. {
  12. _drawingSurface = graphicsDevice.CreateDrawingSurface(e.NewSize, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
  13. DrawText();
  14. var maskSurfaceBrush = compositor.CreateSurfaceBrush(_drawingSurface);
  15. spriteTextVisual.Brush = maskSurfaceBrush;
  16. spriteTextVisual.Size = e.NewSize.ToVector2();
  17. };
  18. RegisterPropertyChangedCallback(FontSizeProperty, new DependencyPropertyChangedCallback((s, e) =>
  19. {
  20. DrawText();
  21. }));
  22. }
  23. private void DrawText()
  24. {
  25. if (ActualHeight == 0 || ActualWidth == 0 || string.IsNullOrWhiteSpace(Text) || _drawingSurface == null)
  26. return;
  27. var width = (float)ActualWidth;
  28. var height = (float)ActualHeight;
  29. using (var session = CanvasComposition.CreateDrawingSession(_drawingSurface))
  30. {
  31. session.Clear(Colors.Transparent);
  32. using (var textFormat = new CanvasTextFormat()
  33. {
  34. FontSize = (float)FontSize,
  35. Direction = CanvasTextDirection.LeftToRightThenTopToBottom,
  36. VerticalAlignment = CanvasVerticalAlignment.Center,
  37. HorizontalAlignment = CanvasHorizontalAlignment.Center,
  38. })
  39. {
  40. using (var textLayout = new CanvasTextLayout(session, Text, textFormat, width, height))
  41. {
  42. if (ShowNonOutlineText)
  43. {
  44. session.DrawTextLayout(textLayout, 0, 0, FontColor);
  45. }
  46. using (var textGeometry = CanvasGeometry.CreateText(textLayout))
  47. {
  48. var dashedStroke = new CanvasStrokeStyle()
  49. {
  50. DashStyle = DashStyle
  51. };
  52. session.DrawGeometry(textGeometry, OutlineColor, (float)StrokeWidth, dashedStroke);
  53. }
  54. }
  55. }
  56. }
  57. }
  58. //SOME CODE AND PROPERTIES
  59. }

5. 结语

文章开头的那个番茄钟源码可以在这里查看:

OnePomodoro_OutlineTextView.xaml at master

也可以安装我的番茄钟应用试玩一下,安装地址:

一个番茄钟

6. 参考

CanvasComposition Class

CanvasDrawingSession Class

CanvasGeometry Class

CompositionGraphicsDevice Class (Windows.UI.Composition) - Windows UWP applications _ Microsoft Docs

CompositionDrawingSurface Class (Windows.UI.Composition) - Windows UWP applications _ Microsoft Docs

CompositionGraphicsDevice Class (Windows.UI.Composition) - Windows UWP applications _ Microsoft Docs

CompositionSurfaceBrush Class (Windows.UI.Composition) - Windows UWP applications _ Microsoft Docs

[UWP]用Win2D实现镂空文字的更多相关文章

  1. win10 uwp 通过 Win2d 完全控制笔迹绘制逻辑

    本文来告诉大家如何通过 Win2d 完全控制笔迹绘制逻辑,本文适合用来实现复杂的自定义逻辑,可以完全控制笔迹的行为.包括在书写过程中切换模式,如进行手势擦除切换为橡皮擦模式 本文提供的方法适合用来做复 ...

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

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

  3. uwp 用win2d获取图片主调颜色

    win10在设置颜色里有个从“背景图片中选取一种主题颜色”的选项,还有在很多内容展示软件中都使用了这样的功能. 现在我们需要在 nuget 引用 win2d.uwp 和 Toolkit.uwp 两个库 ...

  4. 【WIN10】WIN2D——繪製文字

    先看下截圖: 做了幾個效果:普通.倒影.陰影.歌詞. 普通效果代碼: private void normal_Draw(Microsoft.Graphics.Canvas.UI.Xaml.Canvas ...

  5. [UWP]使用Win2D的BorderEffect实现图片的平铺功能

    1. WPF有,而UWP没有的图片平铺功能 在WPF中只要将ImageSource的TileMode属性设置为Tile即可实现图片的平铺,具体可见WPF的这些文档: ImageBrush 类 (Sys ...

  6. [UWP]抄抄《CSS 故障艺术》的动画

    1. 前言 什么是故障艺术(Glitch Art 风)?我们熟知的抖音的 LOGO 正是故障艺术其中一种表现形式.它有一种魔幻的感觉,看起来具有闪烁.震动的效果,很吸引人眼球.故障艺术它模拟了画面信号 ...

  7. 让CSS3给你的文字加上边框宽度,并实现镂空效果

    这次,我主要向大家介绍一下CSS3下的-webkit-text-stroke属性,并分享几个用该属性制作的镂空文字效果. 1.-webkit-text-stroke属性简介 CSS边框的一个不足就是只 ...

  8. win10 uwp win2d CanvasVirtualControl 与 CanvasAnimatedControl

    本文来告诉大家 CanvasVirtualControl ,在什么时候使用这个控件. 在之前的入门教程win10 uwp win2d 入门 看这一篇就够了我直接用的是CanvasControl,实际上 ...

  9. Webkit 文字和背景效果

    -webkit-background-clip:padding-box | border-box | content-box | text,指定对象的背景图像向外裁剪的区域.对应的脚本特性为backg ...

随机推荐

  1. linux+jenkins+postman持续集成

    环境搭建:linux上安装newman,部署好jenkins linux上war包方式安装Jenkins 以下实现jenkins上执行postman测试脚本: 1.新建一个自动风格的job 2.构建- ...

  2. eclipse提交代码到GitHub

    1.配置git 2.右键项目--> Team--> Share Project... 3.右键项目--> Team--> Commit...

  3. 移动端真机调试--weinre

    一.安装 首先确保你的电脑上有node环境,然后使用cnpm或npm 安装 windows下 npm install weinre -g --registry=https://registry.npm ...

  4. 百万年薪python之路 -- 前端CSS样式

    CSS样式 控制高度和宽度 width宽度 height高度 块级标签能设置高度和宽度,而内联标签不能设置高度和宽度,内联标签的高度宽度由标签内部的内容来决定. 示例: <!DOCTYPE ht ...

  5. LaTeX常用篇(三)---矩阵与表格

    目录 1. 序言 2. 矩阵 2.1 复杂写法 2.2 简化写法 2.3 复杂矩阵 3. 表格 4. 对齐 更新时间:2019.10.02 1. 序言   矩阵是一个强大的工具,许多东西都能够用矩阵来 ...

  6. 《编写可维护的JavaScript》 笔记

    <编写可维护的JavaScript> 笔记 我的github iSAM2016 概述 本书的一开始介绍了大量的编码规范,并且给出了最佳和错误的范例,大部分在网上的编码规范看过,就不在赘述 ...

  7. Android9.0 如何区分SDK接口和非 SDK接口

    刚刚有同学问我,不太了解 "非SDK接口" 是什么意思?android9.0有什么限制 ?apache的http也有限制 ? 而且现在的大部分系统都升级上来了,黑名单.灰名单和白名 ...

  8. 你好,Go语言

    本文是「vangoleo的Go语言学习笔记」系列文章之一. 官网: http://www.vangoleo.com/go/hello-golang/ 我在2015年第一次接触Go语言,完成了Hello ...

  9. Spring MVC(1)Spring MVC的初始化和流程以及SSM的实现

    一.Spring MVC概述 1.Spring MVC 的架构 对于持久层而言,随着软件的发展,迁移数据库的可能性很小,所以在大部分情况下都用不到Hibernate的HQL来满足迁移数据库的要求.与此 ...

  10. Texture to texture2D以及texture2D像素反转

    private void SaveRenderTextureToPNG(Texture inputTex, string file) { RenderTexture temp = RenderText ...