[UWP]用Win2D实现镂空文字
1. 前言
之前用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:
var canvasDevice = CanvasDevice.GetSharedDevice();
3.2 CanvasComposition.CreateCompositionGraphicsDevice
然后创建一个Compositor,并将这个Compositor和CanvasDevice关联起来,这里需要使用 CanvasComposition 创建 GraphicsDevice:
var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, canvasDevice);
3.3 CompositionGraphicsDevice.CreateDrawingSurface
然后使用CompositionGraphicsDevice.CreateDrawingSurface创建一个CompositionDrawingSurface对象,它是用来绘画内容的表面:
var drawingSurface = graphicsDevice.CreateDrawingSurface(e.NewSize, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
3.4 Compositor.CreateSurfaceBrush
使用Compositor.CreateSurfaceBrush创建一个CompositionSurfaceBrush,它的作用是使用像素绘制SpriteVisual,简单来说它就是一张位图,然后输出到SpriteVisual上:
var maskSurfaceBrush = compositor.CreateSurfaceBrush(drawingSurface);
spriteTextVisual.Brush = maskSurfaceBrush;
3.5 CanvasComposition.CreateDrawingSession
有了CompositionDrawingSurface就可以为所欲为了,将这个DrawingSurface作为参数,调用CanvasComposition.CreateDrawingSession创建DrawingSession,DrawingSession提供了多个函数,可以自由地在DrawingSurface上画文字、形状、图片甚至SVG。
using (var session = CanvasComposition.CreateDrawingSession(drawingSurface))
{
}
3.6 CanvasTextFormat和CanvasTextLayout
要再DrawingSurface上写字,需要CanvasTextLayout,而CanvasTextLayout中的文字大小、格式等则由CanvasTextFormat定义:
using (var textFormat = new CanvasTextFormat()
{
FontSize = (float)FontSize,
Direction = CanvasTextDirection.LeftToRightThenTopToBottom,
VerticalAlignment = CanvasVerticalAlignment.Center,
HorizontalAlignment = CanvasHorizontalAlignment.Center,
})
{
using (var textLayout = new CanvasTextLayout(session, Text, textFormat, width, height))
{
Color fontColor = FontColor;
session.DrawTextLayout(textLayout, 0, 0, fontColor);
}
}
3.7 CanvasGeometry.CreateText
因为我的目标是镂空的文字,所以不能直接使用DrawTextLayout。这里需要使用CanvasGeometry.CreateText从TextLayout获取一个Geometry,然后使用DrawGeometry将它画到DrawingSurface。CanvasStrokeStyle是可选的,它控制边框的虚线。
using (var textGeometry = CanvasGeometry.CreateText(textLayout))
{
var dashedStroke = new CanvasStrokeStyle()
{
DashStyle = DashStyle
};
session.DrawGeometry(textGeometry, OutlineColor, (float)StrokeWidth, dashedStroke);
}
4. 封装为控件
将上面的代码总结一下,封装为一个OutlineTextControl 控件,它提供了Text、OutlineColor、FontColor等属性,在控件SizeChanged时,或者各个属性改变时调用DrawText重新在CompositionDrawingSurface上绘制文字。代码大致如下:
public class OutlineTextControl : Control
{
private CompositionDrawingSurface _drawingSurface;
public OutlineTextControl()
{
var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, CanvasDevice.GetSharedDevice());
var spriteTextVisual = compositor.CreateSpriteVisual();
ElementCompositionPreview.SetElementChildVisual(this, spriteTextVisual);
SizeChanged += (s, e) =>
{
_drawingSurface = graphicsDevice.CreateDrawingSurface(e.NewSize, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
DrawText();
var maskSurfaceBrush = compositor.CreateSurfaceBrush(_drawingSurface);
spriteTextVisual.Brush = maskSurfaceBrush;
spriteTextVisual.Size = e.NewSize.ToVector2();
};
RegisterPropertyChangedCallback(FontSizeProperty, new DependencyPropertyChangedCallback((s, e) =>
{
DrawText();
}));
}
private void DrawText()
{
if (ActualHeight == 0 || ActualWidth == 0 || string.IsNullOrWhiteSpace(Text) || _drawingSurface == null)
return;
var width = (float)ActualWidth;
var height = (float)ActualHeight;
using (var session = CanvasComposition.CreateDrawingSession(_drawingSurface))
{
session.Clear(Colors.Transparent);
using (var textFormat = new CanvasTextFormat()
{
FontSize = (float)FontSize,
Direction = CanvasTextDirection.LeftToRightThenTopToBottom,
VerticalAlignment = CanvasVerticalAlignment.Center,
HorizontalAlignment = CanvasHorizontalAlignment.Center,
})
{
using (var textLayout = new CanvasTextLayout(session, Text, textFormat, width, height))
{
if (ShowNonOutlineText)
{
session.DrawTextLayout(textLayout, 0, 0, FontColor);
}
using (var textGeometry = CanvasGeometry.CreateText(textLayout))
{
var dashedStroke = new CanvasStrokeStyle()
{
DashStyle = DashStyle
};
session.DrawGeometry(textGeometry, OutlineColor, (float)StrokeWidth, dashedStroke);
}
}
}
}
}
//SOME CODE AND PROPERTIES
}
5. 结语
文章开头的那个番茄钟源码可以在这里查看:
OnePomodoro_OutlineTextView.xaml at master
也可以安装我的番茄钟应用试玩一下,安装地址:
6. 参考
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实现镂空文字的更多相关文章
- win10 uwp 通过 Win2d 完全控制笔迹绘制逻辑
本文来告诉大家如何通过 Win2d 完全控制笔迹绘制逻辑,本文适合用来实现复杂的自定义逻辑,可以完全控制笔迹的行为.包括在书写过程中切换模式,如进行手势擦除切换为橡皮擦模式 本文提供的方法适合用来做复 ...
- [UWP]用Win2D和CompositionAPI实现文字的发光效果,并制作动画
1. 成果 献祭了周末的晚上,成功召唤出了上面的番茄钟.正当我在感慨"不愧是Shadow大人,这难道就是传说中的五彩斑斓的黑?" "那才不是什么阴影效果,那是发光效果.& ...
- uwp 用win2d获取图片主调颜色
win10在设置颜色里有个从“背景图片中选取一种主题颜色”的选项,还有在很多内容展示软件中都使用了这样的功能. 现在我们需要在 nuget 引用 win2d.uwp 和 Toolkit.uwp 两个库 ...
- 【WIN10】WIN2D——繪製文字
先看下截圖: 做了幾個效果:普通.倒影.陰影.歌詞. 普通效果代碼: private void normal_Draw(Microsoft.Graphics.Canvas.UI.Xaml.Canvas ...
- [UWP]使用Win2D的BorderEffect实现图片的平铺功能
1. WPF有,而UWP没有的图片平铺功能 在WPF中只要将ImageSource的TileMode属性设置为Tile即可实现图片的平铺,具体可见WPF的这些文档: ImageBrush 类 (Sys ...
- [UWP]抄抄《CSS 故障艺术》的动画
1. 前言 什么是故障艺术(Glitch Art 风)?我们熟知的抖音的 LOGO 正是故障艺术其中一种表现形式.它有一种魔幻的感觉,看起来具有闪烁.震动的效果,很吸引人眼球.故障艺术它模拟了画面信号 ...
- 让CSS3给你的文字加上边框宽度,并实现镂空效果
这次,我主要向大家介绍一下CSS3下的-webkit-text-stroke属性,并分享几个用该属性制作的镂空文字效果. 1.-webkit-text-stroke属性简介 CSS边框的一个不足就是只 ...
- win10 uwp win2d CanvasVirtualControl 与 CanvasAnimatedControl
本文来告诉大家 CanvasVirtualControl ,在什么时候使用这个控件. 在之前的入门教程win10 uwp win2d 入门 看这一篇就够了我直接用的是CanvasControl,实际上 ...
- Webkit 文字和背景效果
-webkit-background-clip:padding-box | border-box | content-box | text,指定对象的背景图像向外裁剪的区域.对应的脚本特性为backg ...
随机推荐
- javascript获取坐标/滚动/宽高/距离
坐标(鼠标/触摸) event.screenX 鼠标/触摸,相对于显示屏的X坐标 event.screenY 鼠标/触摸,相对于显示屏的Y坐标 event.clientX 鼠标/触摸,相对于浏览器视口 ...
- 用Wireshark抓包分析请求
前言 有些封装好的API把错误都屏蔽掉,直接返回某一个不明确的具体错误,让人感到困惑. //code in SDK read-only public static Data requestHandle ...
- 设计模式(五)Singleton模式
Singleton模式就是确保只生成一个实例的模式.这里有两个意思,即想确保任何情况下都绝对只有一个实例和想在程序上表现出“只存在一个实例”. 下面通过一个实例来说明这种设计模式. package B ...
- DirectX9:基础篇 第一章 初始化Direct3D
一.简介 二.Direct3D类 1.创建D3D类 IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion); //Direct3D类的创建 IDirec ...
- windows系统先安装hexo
一.安装node.js 下载地址为:https://nodejs.org/en/可以根据自己需要下载对于的版本. 打开cmd,输入指令 node -v 若出现上图这样的结果则说明安装好了. 二.安装h ...
- UE4蓝图与C++交互——射击游戏中多武器系统的实现
回顾 学习UE4已有近2周的时间,跟着数天学院"UE4游戏开发"课程的学习,已经完成了UE4蓝图方面比较基础性的学习.通过UE4蓝图的开发,我实现了类似CS的单人版射击游戏,效 ...
- Java后端开发工作 - 写接口
我在公司的工作内容是,对于一个BS应用,负责服务器端开发工作,Java语言.与前端开发人员合作,最终提供给前端RESTFUL接口,保证页面正常响应. 经验之谈 一个接口可以理解为一个业务逻辑,一个业务 ...
- API 网关知识看这篇就足够了!
本文已经收录自 JavaGuide (60k+ Star[Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.) 本文授权转载自:https://github.com/java ...
- 医生智能提醒小程序数据库设计心得——Legends Never Die
数据库设计心得 根据我们小组数据库设计的整个流程,我们将整个数据库设计划分为两个具体的阶段,在每个阶段需要进行不同的准备,有不同的注意事项,接下来我们将结合在数据库设计过程中遇到的一些问题和困难,提出 ...
- 学习笔记34_EF上下文管理
*上下文对象dbContext最好不要频繁的使用Using(var dbContext = new ....):那么就会产生过多的数据库交互:而且每个dbContext中村的数据,由于操作不同,数据可 ...