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

20 篇文章 0 订阅
4 篇文章 0 订阅

© 2012-2023 Conmajia

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

图 1. 带字幕的动画截图(Wong Shao Voon)

常见的几种描边实现方法

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

图 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 最后显示的效果一样,这就是一种“描边”。

图 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);
 

下面请欣赏效果

结语

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Conmajia

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值