博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
换个思路更简单:方便好用的文字描边效果实现方法
阅读量:2455 次
发布时间:2019-05-10

本文共 2037 字,大约阅读时间需要 6 分钟。

© 版权所有 野比 2012

当我们需要在色彩丰富的图片上显示文字的时候,由于背景色变化的关系,文字往往不能清晰呈现。就像很多早期电影使用纯白色字幕,在蓝天白云的画面下常常看不清楚字幕。这时候,我们就需要文字描边这种能够突出显示文字的效果了,就像这样。

(动画截图 by Wong Shao Voon)

 那么,怎样实现这样的效果呢?下面我粗略介绍下目前常见的几种方法。最后介绍我构思的一种简单而实用的实现方法。

一般方法

第一种思路:文字即图片

  1. 将TextBlock 转换为WriteableBitmap
  2. 对WriteableBitmap 的Pixels 进行循环,判断每一个像素点的值最终达到描边的效果。

参考《》

野比点评

这种思路将文字转为图片,根据判断图片上每个像素点,效率低下,最终效果简单,如下图所示。

第二种思路:像素着色器

该方法基本思路为:假定只会对TextBlock应用像素着色器,那么TextBlock是一个矩形,文字所在像素的 alpha分量必定大于0,否则必定是透明像素。判断如果当前像素的上,下,左,右任意一个像素不透明,则说明本像素需要被描边,否则就输出文字颜色。由于需要知道相邻像素,所以还需要传入TextBlock的ActualWidth和ActualHeight。 这样, 当前位置的 x+ 1/width 就是相邻像素的坐标,就可以用tex2D函数来提取它的颜色值。还需要输入描边的颜色,还有文字的颜色。

参考《》

野比点评

仍然是一个「大炮打蚊子」的思路,将文字进行逐像素的处理。和思路1唯一的区别在于使用了像素着色器,让把部分工作交给GPU来完成,「看起来」很高效很快速。但是如果禁用了硬件加速呢?就变成和1一样了。下面是该方法的效果截图。

第三种思路:GDI+路径绘图

这种方法不再是逐像素处理了。其基本思路是将文字字符串添加到GDI+的绘图路径中(GraphicsPath),然后再DrawPath()。利用不同的笔刷,这种方法可以「画」出非常华丽的描边效果,就像这样。

野比点评

这是扩展性最好的方法。由于利用了GDI+的高级特性,所以可以利用不同的笔刷如纹理、渐变,以及多次绘图等方法做出非常精美的描边、阴影效果。唯一的遗憾就是代码量较大(比前面2种要少很多了)。

参考文章《》

关于该方法的高级效果设计,参考《》一文(Code Project「Best C++/MFC article of Sep 2009」比赛获奖文章)。

 

野比的简易方法

又到了野比的偷懒时间。

看了前面几种设计思路后,你有没有一头雾水的感觉?或者眼花缭乱的感觉?难道我们只有这样实现吗?需要「描边」文字,就一定要「描」吗?

其实完全没有必要。曾经我在山寨Safari时,介绍过一种简单的通过重复绘制文字实现高光效果的方法(参见《》)。

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

接下来在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);

下面请欣赏效果

 

结语

很多时候,我们遇到问题,不一定需要完全跟着问题走。就像这次,我们需要「描边」,但谁说的,我们非得要「描」边呢?我们要的只是效果,而不是过程,所以要跳出问题表象的禁锢,就能获得更加宽广的视野。

© 版权所有 野比 2012

(全文完)

转载地址:http://uxdhb.baihongyu.com/

你可能感兴趣的文章
应用宝应用认领并签名_通过“我已被认领”检查您的密码安全性吗? 并通过
查看>>
playground_开始修补Circuit Playground Express
查看>>
gcc编译和交叉编译_32位生命支持:与GCC交叉编译
查看>>
basic编程命令_从BASIC到Ruby:命令行英雄的第一门编程语言的生活课
查看>>
开源教学系统_通过开源进行教学和口语学习
查看>>
2k19徽章修改_您可以修改此会议徽章
查看>>
命令行python路径命令_探索命令行英雄中Python的过去,现在和未来
查看>>
Codethink开源是入职流程的一部分
查看>>
自动部署 管道 ci cd_每个产品只有一条CI / CD管道来统治它们
查看>>
centos7实验手册_一个小时内创建一个CentOS家庭实验室
查看>>
在命令行英雄的浏览器大战中,JavaScript令人惊讶地崛起
查看>>
vc++编写播放器_为什么此开发人员用C ++编写音乐播放器
查看>>
openssl哈希_如何使用OpenSSL:哈希,数字签名等
查看>>
openssl密码库_OpenSSL入门:密码学基础
查看>>
一个组织可以同时有很多领导_建立一个不断学习的组织:领导者的提示
查看>>
cobol基础_基础架构是代码:COBOL和Go的故事
查看>>
linux内核测试_Linux内核的持续集成测试
查看>>
okd 安装_在OKD中创建源到图像构建管道
查看>>
json文件转化为图像文件_如何将Excel文件转换为HTML或JSON
查看>>
使用GHTorrent和Libraries.io查询十年的GitHub数据
查看>>