畫(huà)圖
在iOS中實(shí)現(xiàn)繪圖的技術(shù)的話,比較通用的做法是簇搅,在onTouch事件中收集到軌跡坐標(biāo)點(diǎn)數(shù)據(jù)完域,然后在UIView中的drawInRect
方法里面繪制每一幀畫(huà)面。在drawInRect
方法使用CGContextRef的方法如CGContextAddLineToPoint等來(lái)實(shí)現(xiàn)馍资。一般來(lái)說(shuō)筒主,可以每?jī)蓚€(gè)點(diǎn)連成一條直線,然后把軌跡繪制出來(lái)鸟蟹。
但是這樣的話乌妙,如果一定時(shí)間內(nèi),繪畫(huà)的速度比較快建钥,屏幕產(chǎn)生的點(diǎn)的距離就變得比較遠(yuǎn)藤韵,這樣兩個(gè)點(diǎn)之間產(chǎn)生的直線連接起來(lái)看起來(lái)就比較有輪廓感。
CGContextRef context = UIGraphicsGetCurrentContext(); //設(shè)置上下文
//畫(huà)一條直線
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);//線條顏色
CGContextSetLineWidth(context, 5.0);//線條寬度
CGContextMoveToPoint(context, 100, 100); //開(kāi)始畫(huà)線, (100熊经,100) 為開(kāi)始點(diǎn)的坐標(biāo)
CGContextAddLineToPoint(context, 200, 200);//畫(huà)直線, (200泽艘,200)為線條結(jié)束點(diǎn)的坐標(biāo)
CGContextStrokePath(context); //開(kāi)始畫(huà)線
CGContextRelease(context);
如下圖所示:
貝塞爾插值法優(yōu)化
首先要知道貝塞爾曲線的定義,以下是二階貝塞爾曲線公式镐依。
二階貝塞爾曲線的意思是匹涮,只有一個(gè)控制點(diǎn)P1,起點(diǎn)和終點(diǎn)分別是P0和P3槐壳。(三階貝塞爾曲線有兩個(gè)控制點(diǎn))當(dāng)t=0的時(shí)候然低,B(t)的值等于P0,當(dāng)t=1的時(shí)候,B(t)的值等于P2雳攘。P1是控制點(diǎn)带兜,用來(lái)控制起點(diǎn)P0和終點(diǎn)P2之間的彎曲程度。
所以吨灭,可以使用每三個(gè)點(diǎn)來(lái)組成一段二階貝塞爾曲線刚照,然后使用二階貝塞爾曲線方程進(jìn)行中間插值。這樣起點(diǎn)P0和新產(chǎn)生的插值點(diǎn)就形成了新的軌跡喧兄。Pn為復(fù)合二階貝塞爾曲線的插值坐標(biāo)點(diǎn)无畔,由貝塞爾曲線的t從[0,1]變化來(lái)產(chǎn)生。
進(jìn)一步優(yōu)化
貝塞爾曲線中點(diǎn)優(yōu)化
經(jīng)過(guò)第一步優(yōu)化繁莹,效果好了不少檩互,圓滑效果也出來(lái)了特幔,但是可以進(jìn)一步優(yōu)化咨演,可以計(jì)算P0與P1之間的中點(diǎn)Pm0,P1與P2之間的中點(diǎn)Pm1蚯斯,還是以P1為控制點(diǎn)薄风,這樣【Pm0,P1,Pm2】作為二階貝塞爾曲線的新的起點(diǎn)拍嵌、控制點(diǎn)遭赂、終點(diǎn)。
這樣的話横辆,軌跡的第一個(gè)點(diǎn)和最后一個(gè)點(diǎn)就孤立出來(lái)了撇他,可以直接把第一個(gè)點(diǎn)和第一個(gè)中點(diǎn)用直線連接便可。
繪制速度優(yōu)化
上述優(yōu)化是強(qiáng)制每3個(gè)坐標(biāo)點(diǎn)都做插值優(yōu)化狈蚤,這樣產(chǎn)生的插值點(diǎn)就會(huì)非常多困肩,因?yàn)槔L制的速度
是可以通過(guò)固定時(shí)間內(nèi)產(chǎn)生的坐標(biāo)點(diǎn)來(lái)判斷的,所以可以通過(guò)速度來(lái)控制是否要進(jìn)行插值脆侮,如果速度非常慢锌畸,達(dá)不到插值的閾值,可以直接用直線連接靖避。
如果速度非程对妫快,需要插值幻捏,這時(shí)候盆犁,插值點(diǎn)的多少還是要經(jīng)過(guò)二階貝塞爾曲線方程t來(lái)判斷,速度越快篡九,t從[0,1]的變換越慢谐岁,這樣產(chǎn)生的插值點(diǎn)才會(huì)越多。