張耀東,張慧娟
上海同濟(jì)大學(xué)軟件學(xué)院嵌入式系統(tǒng)實(shí)驗(yàn)室,上海 201804
一般在PC機(jī)上,我們用Flash來(lái)實(shí)現(xiàn)漢字書(shū)寫(xiě)這個(gè)動(dòng)作,但是目前iPhone并不支持Flash,所以只能自寫(xiě)類(lèi)似Flash中的動(dòng)態(tài)填充算法。對(duì)于動(dòng)態(tài)填充動(dòng)作,一般的處理是由一點(diǎn)朝一個(gè)方向的逐步填充:設(shè)置給定區(qū)域內(nèi)的點(diǎn)的顏色為預(yù)設(shè)的顏色。Quartz 2D庫(kù)里沒(méi)有設(shè)置給定點(diǎn)顏色的函數(shù),但是通過(guò)向指定方向移動(dòng)的過(guò)程中繪制直線也能實(shí)現(xiàn)填充,這樣做的效率非常低。但是如果用擋板移動(dòng)模擬填充動(dòng)畫(huà)可以實(shí)現(xiàn)同樣的功能,且效率極高。近來(lái)國(guó)內(nèi)iPhone SDK開(kāi)發(fā)各種應(yīng)用程序進(jìn)行得如火如荼,本文介紹的功能也是基于iPhone平臺(tái)進(jìn)行開(kāi)發(fā)的一次新嘗試,對(duì)那些想在iPhone平臺(tái)上研究的程序員有很大的幫助。
本文的重點(diǎn)在于:詳細(xì)地介紹漢字的動(dòng)態(tài)書(shū)寫(xiě)展示的實(shí)現(xiàn)步驟。
首先,在信息源中漢字的筆畫(huà)信息已經(jīng)以三次Bezier曲線表示出來(lái),而且三次Bezier曲線以點(diǎn)陣的形式存儲(chǔ),即包含一個(gè)起始點(diǎn),兩個(gè)控制點(diǎn),一個(gè)終點(diǎn);
其次,一個(gè)復(fù)雜筆畫(huà)用筆畫(huà)拆分算法拆分為多個(gè)單向不交錯(cuò)的筆畫(huà)段,這步保證筆畫(huà)段每次展示不會(huì)同時(shí)出現(xiàn)的錯(cuò)誤現(xiàn)象。
1)從數(shù)據(jù)文件中讀出漢字筆畫(huà)信息(ReadDataFromFile)
(1)讀取第一條Bezier曲線的起始點(diǎn);
(2)順序讀取當(dāng)前Bezier曲線的控制點(diǎn)1,控制點(diǎn)2,終點(diǎn);
(3)若一個(gè)筆畫(huà)段的讀取未結(jié)束,將上一條Bezier曲線的終點(diǎn)賦予下一條Bezier曲線的起始點(diǎn),回到步驟1.2;否則到步驟1.4;
(4)若數(shù)據(jù)流未結(jié)束,回到步驟1.1;否則結(jié)束功能塊。
2)繪制筆畫(huà)段
(1)順序繪制出筆畫(huà)段所包含的Bezier曲線;
通過(guò)適當(dāng)設(shè)置筆畫(huà)段邊界線的寬度以掩蓋由于筆畫(huà)分割精度造成的筆畫(huà)段間出現(xiàn)的縫隙。
(2)填充閉合區(qū)域
信息數(shù)據(jù)的存儲(chǔ)方式?jīng)Q定了一個(gè)筆畫(huà)段中所有Bezier曲線首位相接。
3)以書(shū)寫(xiě)順序的倒置順序逐個(gè)將筆畫(huà)段視圖添加到主視圖中(AddSubView);
為漢字書(shū)寫(xiě)做準(zhǔn)備,按照層次性將依附在主視圖上的筆畫(huà)段子視圖一層一層顯示出來(lái),這樣,漢字書(shū)寫(xiě)時(shí)筆畫(huà)順序就能展示出來(lái)。
筆畫(huà)段視圖opaque = NO,這樣,筆畫(huà)段視圖間才不會(huì)出現(xiàn)彼此覆蓋的情況。
4)在主視圖上隱藏所有的筆畫(huà)段視圖(hidden = YES);
5)添加一個(gè)計(jì)時(shí)器
計(jì)時(shí)器的作用是讓程序每隔一段時(shí)間(interval)執(zhí)行OnTimer函數(shù)。展示一個(gè)筆畫(huà)段需要一段動(dòng)畫(huà)時(shí)間,這段時(shí)間內(nèi),程序需要等待。
OnTimer:(repeats = NO,不重復(fù)運(yùn)行,因?yàn)闀r(shí)間間隔根據(jù)筆畫(huà)段長(zhǎng)度或?qū)挾葧?huì)有改變)
6)顯示下一個(gè)將要顯示的筆畫(huà)段視圖(hidden = NO);
7)在下一個(gè)將要顯示的筆畫(huà)段視圖之上添加擋板視圖(InsertSubView);
(1)設(shè)置擋板視圖opaque = YES,背景色與主視圖一致;
(2)分別得到下一個(gè)將要顯示的筆畫(huà)段視圖的最上點(diǎn)、最下點(diǎn)、最左點(diǎn)、最右點(diǎn),以這4個(gè)點(diǎn)來(lái)構(gòu)造一個(gè)正向的矩形區(qū)域,在這個(gè)矩形區(qū)域新建一個(gè)擋板視圖。擋板簡(jiǎn)單地說(shuō)即是一個(gè)顏色與背景色相同且不透明的矩形局域。
構(gòu)造這樣一個(gè)矩形區(qū)域的目的是為了避免出現(xiàn)擋板的無(wú)效移動(dòng):擋板把筆畫(huà)段視圖上的空白區(qū)域也看成要展示的區(qū)域。
(3)在主視圖上,將新建的擋板視圖添加到下一個(gè)將要顯示的筆畫(huà)段視圖之上。
8)移動(dòng)擋板視圖
(1)得到擋板將要移動(dòng)的方向(上下左右);
暫時(shí)是以筆畫(huà)段的中點(diǎn)和起始點(diǎn)連線的斜率來(lái)判斷。
(2)計(jì)算出擋板移動(dòng)后所停留的位置及移動(dòng)所需時(shí)間;
(3)加入并執(zhí)行動(dòng)畫(huà)
為了使筆畫(huà)間的書(shū)寫(xiě)更加平滑,根據(jù)一個(gè)筆畫(huà)的寬度(上移和下移)或者長(zhǎng)度(左移和右移),設(shè)定動(dòng)畫(huà)的時(shí)間。
(4)銷(xiāo)毀擋板視圖
9)若所有筆畫(huà)段視圖都顯示出來(lái),則結(jié)束流程;否則回到步驟6。
下面通過(guò)兩幅圖片,來(lái)直觀地看擋板算法的具體效果:
圖2.1 是當(dāng)一個(gè)復(fù)雜筆畫(huà)被拆分為多個(gè)筆畫(huà)段后,當(dāng)中的一個(gè)筆畫(huà)段的展示情況;圖2.2是一個(gè)普通筆畫(huà)的展示情況。
圖2.1
圖2.2
可以發(fā)現(xiàn)運(yùn)行效果和用Flash做的效果是一樣的,而且由于使用的擋板移動(dòng)并不耗費(fèi)時(shí)間,算法中也不存在太多嵌套循環(huán),所以效率是非常高的。
[1]喬納森.AppStore掘金 —— iPhone.
[2]SDK應(yīng)用程序開(kāi)發(fā).人民郵電,2010,1.
[3]Erica Sadun.iPone開(kāi)發(fā)秘籍.人民郵電,2009,7.
[4]Stephen G.Kochan,Objective-C 2.0程序設(shè)計(jì).2版.機(jī)械工業(yè)出版社,2009,8.