首页 技术 正文
技术 2022年11月17日
0 收藏 720 点赞 3,171 浏览 5055 个字

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

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. 参考

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

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,071
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,549
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,397
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,174
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,809
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,889