张耀东,张慧娟
上海同济大学软件学院嵌入式系统实验室,上海 201804
一般在PC机上,我们用Flash来实现汉字书写这个动作,但是目前iPhone并不支持Flash,所以只能自写类似Flash中的动态填充算法。对于动态填充动作,一般的处理是由一点朝一个方向的逐步填充:设置给定区域内的点的颜色为预设的颜色。Quartz 2D库里没有设置给定点颜色的函数,但是通过向指定方向移动的过程中绘制直线也能实现填充,这样做的效率非常低。但是如果用挡板移动模拟填充动画可以实现同样的功能,且效率极高。近来国内iPhone SDK开发各种应用程序进行得如火如荼,本文介绍的功能也是基于iPhone平台进行开发的一次新尝试,对那些想在iPhone平台上研究的程序员有很大的帮助。
本文的重点在于:详细地介绍汉字的动态书写展示的实现步骤。
首先,在信息源中汉字的笔画信息已经以三次Bezier曲线表示出来,而且三次Bezier曲线以点阵的形式存储,即包含一个起始点,两个控制点,一个终点;
其次,一个复杂笔画用笔画拆分算法拆分为多个单向不交错的笔画段,这步保证笔画段每次展示不会同时出现的错误现象。
1)从数据文件中读出汉字笔画信息(ReadDataFromFile)
(1)读取第一条Bezier曲线的起始点;
(2)顺序读取当前Bezier曲线的控制点1,控制点2,终点;
(3)若一个笔画段的读取未结束,将上一条Bezier曲线的终点赋予下一条Bezier曲线的起始点,回到步骤1.2;否则到步骤1.4;
(4)若数据流未结束,回到步骤1.1;否则结束功能块。
2)绘制笔画段
(1)顺序绘制出笔画段所包含的Bezier曲线;
通过适当设置笔画段边界线的宽度以掩盖由于笔画分割精度造成的笔画段间出现的缝隙。
(2)填充闭合区域
信息数据的存储方式决定了一个笔画段中所有Bezier曲线首位相接。
3)以书写顺序的倒置顺序逐个将笔画段视图添加到主视图中(AddSubView);
为汉字书写做准备,按照层次性将依附在主视图上的笔画段子视图一层一层显示出来,这样,汉字书写时笔画顺序就能展示出来。
笔画段视图opaque = NO,这样,笔画段视图间才不会出现彼此覆盖的情况。
4)在主视图上隐藏所有的笔画段视图(hidden = YES);
5)添加一个计时器
计时器的作用是让程序每隔一段时间(interval)执行OnTimer函数。展示一个笔画段需要一段动画时间,这段时间内,程序需要等待。
OnTimer:(repeats = NO,不重复运行,因为时间间隔根据笔画段长度或宽度会有改变)
6)显示下一个将要显示的笔画段视图(hidden = NO);
7)在下一个将要显示的笔画段视图之上添加挡板视图(InsertSubView);
(1)设置挡板视图opaque = YES,背景色与主视图一致;
(2)分别得到下一个将要显示的笔画段视图的最上点、最下点、最左点、最右点,以这4个点来构造一个正向的矩形区域,在这个矩形区域新建一个挡板视图。挡板简单地说即是一个颜色与背景色相同且不透明的矩形局域。
构造这样一个矩形区域的目的是为了避免出现挡板的无效移动:挡板把笔画段视图上的空白区域也看成要展示的区域。
(3)在主视图上,将新建的挡板视图添加到下一个将要显示的笔画段视图之上。
8)移动挡板视图
(1)得到挡板将要移动的方向(上下左右);
暂时是以笔画段的中点和起始点连线的斜率来判断。
(2)计算出挡板移动后所停留的位置及移动所需时间;
(3)加入并执行动画
为了使笔画间的书写更加平滑,根据一个笔画的宽度(上移和下移)或者长度(左移和右移),设定动画的时间。
(4)销毁挡板视图
9)若所有笔画段视图都显示出来,则结束流程;否则回到步骤6。
下面通过两幅图片,来直观地看挡板算法的具体效果:
图2.1 是当一个复杂笔画被拆分为多个笔画段后,当中的一个笔画段的展示情况;图2.2是一个普通笔画的展示情况。
图2.1
图2.2
可以发现运行效果和用Flash做的效果是一样的,而且由于使用的挡板移动并不耗费时间,算法中也不存在太多嵌套循环,所以效率是非常高的。
[1]乔纳森.AppStore掘金 —— iPhone.
[2]SDK应用程序开发.人民邮电,2010,1.
[3]Erica Sadun.iPone开发秘籍.人民邮电,2009,7.
[4]Stephen G.Kochan,Objective-C 2.0程序设计.2版.机械工业出版社,2009,8.