非典型文字描边效果的实现方法

© 2012-2023 Conmajia

文字描边效果主要用于在复杂或颜色近似的背景上区分文字内容。图 1 的动画截图中,字幕文字为浅色,所以采用了深色描边以区分字幕和动画内容。

非典型文字描边效果的实现方法_第1张图片 图 1. 带字幕的动画截图(Wong Shao Voon)

常见的几种描边实现方法

1. 以图片方式处理文字像素并描边。如图 2 所示,首先将 TextBlock 转换为 WriteableBitmap,然后对 Pixels 进行循环,判断像素点值直至达成描边效果。这篇文章 对此进行了详细说明。

非典型文字描边效果的实现方法_第2张图片 图 2. 图片方式处理描边

这种方法将文字转为图片,判断图片上每个像素点,效率较低,最终效果过于简单。

2. 像素着色器。该方法基本思路为:假定只会对 TextBlock 应用像素着色器,那么文字所在像素的 alpha 分量必定大于 0,否则必为透明像素。如果当前像素的上,下,左,右任意一个像素不透明,说明该像素需要描边,否则就输出文字颜色。实际处理方法可以参考 这篇文章​​​​​​​。

3. GDI+ 路径绘图。该方法利用了 GDI+ 中的绘图路径,通过将文字添加到 GraphicsPath 中进行绘制。利用不同的笔刷,这种方法可以得到非常华丽的描边效果,如图 3 所示。

图 3. GDI+ 路径绘图方法实现的描边效果

这种方法的另一优点是扩展性极佳,可以利用不同的笔刷如纹理、渐变,以及多次绘图等方法做出非常精美的描边、阴影效果。Code Project 网站 2009 年 9 月 C++/MFC 版块的最佳获奖文章 Outline Text 对此进行了详细介绍。

我的简易方法

又到了我的偷懒时间。

看了前面几种设计思路后,你有没有一头雾水的感觉?

或者眼花缭乱的感觉?

有没有一种可能,我们需要“描边”文字,但是并不一定非要去“描”它?

我在介绍山寨 Safari 面板时,提到过一种通过重复绘制文字实现简单高光效果的方法(参见《一步一步玩控件:TabControl——从制作山寨 Safari 窗体开始》)。

如图 4 所示,当底层文字和顶层文字相差 1px 时,会呈现出不同的阴影或者高光效果。我们把这个思路拓展一下,把上、下、左、右四个方向的偏差结合到一起,最后得到图 4 最后显示的效果一样,这就是一种“描边”。

非典型文字描边效果的实现方法_第3张图片 图 4. 利用反复文字偏移实现类似描边的显示效果

接下来在GDI+里面实现它。 

// Code by Conmajia
// txtPoint 是绘制文字的定位点
txtPoint.Offset(-1, 0);  // 绘制左背景文字
e.Graphics.DrawString(this.Text, this.Font, backBrush, txtPoint);
txtPoint.Offset(2, 0);  // 绘制右背景文字
e.Graphics.DrawString(this.Text, this.Font, backBrush, txtPoint);
txtPoint.Offset(-1, -1);  // 绘制下背景文字
e.Graphics.DrawString(this.Text, this.Font, backBrush, txtPoint);
txtPoint.Offset(0, 2);  // 绘制上背景文字
e.Graphics.DrawString(this.Text, this.Font, backBrush, txtPoint);
txtPoint.Offset(0, -1);  // 定位点归位
 
// 绘制前景文字
e.Graphics.DrawString(this.Text, this.Font, foreBrush, txtPoint);
 

下面请欣赏效果

非典型文字描边效果的实现方法_第4张图片

结语

很多时候,如果不便于解决问题,那么换一种解决思路不失为一个好的开始。遇到问题,不一定需要完全跟着问题走。有时候跳出问题表象的禁锢,反而能获得更加宽广的视野。

你可能感兴趣的:(图形,C#,山寨,silverlight,safari,c#,扩展,工作)