Canvas文本处理技巧
分类 : HTML5+CSS3, Javascript · by 冷月无声 2015年01月26日
canvas作为HTML5新引入的重要API,提供给我们强大的图形处理和渲染能力,但在文本处理方面,canvas却某些方面略显不是那么擅长,本文将从canvas的文本处理短板入手,分析并解决绘制文本带来的问题。
首先简单归纳一下canvas在文本处理方面几大陋点:
接下来对症下药,依次来解决以上陋点。
自定义字体标题党有误,并不是说canvas不支持自定义字体,只是css的自定义字体文件是异步加载的,假设在异步文件加载完成之前去进行文本的绘制,而此文本恰好又设置了此自定义字体,按照canvas的画布原理,那岂不是跪了。
目前还没有有效的办法去监听css中font-face文件的加载状况,既然没办法监听,倒不如直接造一个相同的请求,利用浏览器cache策略,无论哪个请求先回来,另外一个请求一般都是304吧!
所以造请求的任务就交给ajax了(这里不选择image的原因是,似乎Image对象对非图片类型的资源不相应onload),
将字体文件的url弄给ajax的XMLHttpRequest实例,然后开始异步ajax请求。
等到ajax加载完毕之后,就可以开始进行设置指定的canvas自定义字体了,这时候得注意setTimeout单起一个线程设置哦,要不然会有问题哦。。
文本间隔css中我们常用letter-spacing来设置文本的字符间隔,简单直接有效。
目前观察canvas似乎还没有找到支持文本间隔的API,那么我们就来看看怎么给canvas设置文本间距。
假设我们理想的间隔单位是1em(一个字符)、10px这两种。
首先我们还是要将这些单位统一转换为canvas能够识别的px单位:
接下来我们开始绘制字符,一段带间隔的文本就呈现在美丽的canvas画布上了:
绘制的方法是对字符串进行分割后逐字填写,在这过程中通过添加间隔大小来改变x方向的坐标。
文本换行文本换行相对于前两种来说相对复杂一点,因为这其中涉及到中英文的切换问题。
css中可以通过word-break:break-word;来设置单词换行,用word-break:break-all进行全局换行。
其实用canvas来换行也是轻而易举的事情啦!。
首先得决定换行的条件,在canvas中,一个英文字符和一个中文字符的实际像素宽度是不一样的,一般情况下,中文字符.width = 2*英文字符.width(姑且这样算,可能有大小写、字符特性、不等宽字体等差异),那么我们就愉快地决定以10个英文字符作为换行节点。
我们采用分段逐步绘制的策略来填充文本,首先得申请一个数组,来存放分段的文本。
其次,重要的字符的分割及字符长度的判断,如果遇到单词必须连续的情况,我们还得判断前一个和后一个字符是否都为英文字母或者数字,因为英文字符还包括英文的特殊符号,必须把这部分剔除出去。
循环字符串的时候,每遇到一个英文单词,长度就递增1,每遇到一个中文字符,长度就递增2,累计下去,当每段文本的长度超过换行节点的长度时,就开始进入下一轮循环,开始拼接下一段文本。
最后,我们就按照分段好的文本数组,依次来在canvas上绘制出问题。
按照英文单词来换行
全局换行
另辟蹊径
上面讲了那么多,为了一段简单文字那么折腾,值得吗?那么不少人会问,还有能让人早点睡觉的方法吗?毕竟,现在已经凌晨了,我也很困啊!好吧,为了让自己早点休息,明天努力上班,我也得下血本了!
记得前段时间,我在研究利用canvas实现前端网页截图功能,它的大致原理是:
创建一段svg的dom,然后利用svg的foreignObject元素添加一段带有普通dom元素样式的标签结构;
注意,这种标签结构必须遵守xhtml规范,也就是元素的xmlns属性必须为,
接着将这段svg转化为Blob对象,blob对象的类型为image/svg+xml;
再通过浏览器自带URL对象将这个Blob对象转化为可供普通img标签访问的图片url(也曾试过用FileReader对象来转换);
然后构造一个Image对象,将通过URL转化来的url赋值的图片的src;
等待图片加载完毕,将此图片按照一定的尺寸,位置,截取大小等绘制在canvas画布上;
最后通过canvas的上下文用toDataURL将此图片转化,得到图片的base64编码;
由于base64编码字符串不受页面环境影响,可以存储于后台,因此通过以上步骤完成了截图。
此时的灵感泉涌而至,此文的文本处理似乎也能通过这种原理进行实现。
如果把要处理的文本放入一个可设置css样式的dom元素中,那我们想要的样式,什么字号,什么间距,什么换行,还不是就信手拈来吗?
果断下手,具体实现例子如下:
通过这种方法,前面复杂的处理逻辑一下就变得简单起来,svg还真是如此管用。
那么,问题来了,前面说了那么多,感觉不都是废话吗?到最后还是这个“另辟蹊径”一针见效。
哎呀,该剁手了啊!作为铁杆的canvas粉丝,居然打破承诺写起了死对头svg的代码,这难道不是一种背叛吗?
结语还在为canvas字符处理而烦恼的朋友们,赶紧试试吧!
手写canvas,有这个就够了:
最后,别忘了粉我的前端博客-