CAShapeLayer + BezierPath 處理圖形編輯

我們做圖形編輯的時(shí)候南缓,做了一個(gè)ShapeOperator類來(lái)操作圖形目锭,里面存儲(chǔ)了圖形的尺寸位置和泌、旋轉(zhuǎn)角度等信息村缸,可以生成貝塞爾曲線,將其賦值給 CAShapeLayer即可完成渲染

旋轉(zhuǎn)

SO上找到了操作貝塞爾曲線旋轉(zhuǎn)的最佳實(shí)踐:https://stackoverflow.com/questions/13738364/rotate-cgpath-without-changing-its-position

  • 針對(duì)某個(gè)旋轉(zhuǎn)武氓,先以圖形中心點(diǎn)的負(fù)值做移動(dòng)梯皿,將中心點(diǎn)移動(dòng)到“視圖”左上角,再做旋轉(zhuǎn)县恕,然后再移動(dòng)回來(lái)东羹。
  • 上面涉及三次 transform, 通過(guò) transformConcat連接忠烛,計(jì)算出最終 transfrom属提,賦值給貝塞爾曲線的 transform 屬性

平移

直接改變控制點(diǎn)即可

編輯控制點(diǎn)

以矩形為例,矩形有四個(gè)控制點(diǎn)美尸,即幾個(gè)角冤议,如果沒(méi)有旋轉(zhuǎn),拖動(dòng)任意控制點(diǎn)就能改變圖形的大小师坎,也很直觀恕酸,但是增加了旋轉(zhuǎn)以后,復(fù)雜度陡然提升

矩形的表示
  • 起始點(diǎn) (x, y)
  • 寬度 width
  • 高度 height
  • 旋轉(zhuǎn)角度 rotation
控制點(diǎn)轉(zhuǎn)換
  • 如果沒(méi)有旋轉(zhuǎn)的圖形胯陋,改變的控制點(diǎn)蕊温,很容易對(duì)應(yīng)出起始點(diǎn)和寬高的改變,比如移動(dòng)矩形左上角遏乔,就是把起始點(diǎn)變成拖動(dòng)后的點(diǎn)义矛,對(duì)應(yīng)增加寬高
  • 如果我們?cè)谝粋€(gè)旋轉(zhuǎn)了一定角度的圖形上,拖動(dòng)控制點(diǎn)盟萨,我們需要知道這個(gè)控制點(diǎn)到底如何影響上面的尺寸位置的症革,拖動(dòng)后的點(diǎn)的坐標(biāo),是未旋轉(zhuǎn)的控制點(diǎn)位置鸯旁,追加了旋轉(zhuǎn)角度后的坐標(biāo)
  • 所以第一步是去除旋轉(zhuǎn)的影響噪矛,iOS 為我們提供了 CGPoint 的 transform 變換的計(jì)算方法 CGPointApplyAffineTransform
  • 上面旋轉(zhuǎn)章節(jié)提到,做旋轉(zhuǎn)需要三次 transform铺罢,把它 concat 后的最終 transfrom 做 CGAffineTransformInvert艇挨,再應(yīng)用給新的控制點(diǎn),就得到了矩形未旋轉(zhuǎn)時(shí)的新控制點(diǎn)位置韭赘,這就很容易把對(duì)應(yīng)的起始點(diǎn)和寬高計(jì)算出來(lái)了缩滨,然后再把圖形旋轉(zhuǎn)到對(duì)應(yīng)角度。
  • 但是旋轉(zhuǎn)以后,和以前的圖形就不對(duì)齊了脉漏,這是個(gè)大坑苞冯,什么叫對(duì)齊?下面詳細(xì)說(shuō)
有旋轉(zhuǎn)的控制點(diǎn)變換追加平移
  1. 我們插入了下面的圖形侧巨,邊長(zhǎng) a舅锄,圖形中心點(diǎn) (x, y)
  1. 然后旋轉(zhuǎn)這個(gè)圖形到下圖,
  1. 接著拖動(dòng)圖形最下面的這個(gè)頂點(diǎn)司忱,讓圖形變大成邊長(zhǎng)b皇忿,我們期望的是下圖的效果

想達(dá)到上面的效果,我們有兩種途徑:

  • 旋轉(zhuǎn)中心點(diǎn)不變坦仍,僅改變邊長(zhǎng)尺寸鳍烁,這樣我們?cè)谧鰣D形旋轉(zhuǎn)的時(shí)候,先對(duì)圖形進(jìn)行(-x, -y)的移動(dòng)繁扎,然后旋轉(zhuǎn)幔荒,再進(jìn)行 (x, y) 的移動(dòng),就能滿足上圖的效果(僅最底下的控制點(diǎn)變化了梳玫,其它邊以及頂部控制點(diǎn)與原先重合)铺峭。但是這樣有一個(gè)問(wèn)題,下次旋轉(zhuǎn)的時(shí)候汽纠,就不是沿著圖形中心點(diǎn)旋轉(zhuǎn)了,不過(guò)這個(gè)思路能幫我們找到正確答案
  • 始終保持圖形中心點(diǎn)旋轉(zhuǎn)傀履。但是虱朵,因?yàn)榫庉嫼螅呴L(zhǎng)從 a 變成 b 钓账,圖形中心點(diǎn)會(huì)變成 (x', y')碴犬,那旋轉(zhuǎn)以后,圖形的頂點(diǎn)和其它邊就沒(méi)法與原先重合梆暮,而是像下圖

如果想達(dá)成期望的效果服协,在編輯圖形的時(shí)候,還要對(duì)圖形進(jìn)行平移啦粹,這樣旋轉(zhuǎn)以后就能使頂部的點(diǎn)與原先重合

我們按途徑1偿荷,以不變旋轉(zhuǎn)中心點(diǎn)的方式旋轉(zhuǎn)以后,圖形的中心點(diǎn)變成了 (x", y")唠椭,可以從下圖看到跳纳,(x", y") 與 (x', y') 存在平移,而此平移的變化由來(lái)贪嫂,就是以 (x, y) 為中心寺庄,將(x', y')旋轉(zhuǎn)圖形所旋轉(zhuǎn)的角度,變到了(x", y") ,移動(dòng)量就是 (x" - x', y" - y')

這樣斗塘,在編輯的時(shí)候赢织,計(jì)算編輯前后的中心點(diǎn)變化,并應(yīng)用上面的變換馍盟,得到圖形需要平移的量于置,追加給圖形,就可以達(dá)到預(yù)期的效果了

總結(jié)

圖形編輯朽合,有時(shí)候看起來(lái)很簡(jiǎn)單直觀的事情俱两,在實(shí)際代碼上,就會(huì)非常困難曹步,最近在做曲線的旋轉(zhuǎn)宪彩,又是一個(gè)大坑,因?yàn)榍€的起始點(diǎn)讲婚,終點(diǎn)尿孔、控制點(diǎn)三個(gè)點(diǎn),位置的不同筹麸,決定了曲線的形狀活合,拖動(dòng)終點(diǎn)或起點(diǎn)的時(shí)候,三個(gè)點(diǎn)都會(huì)變化物赶,而且一會(huì)正一會(huì)負(fù)白指,需要根據(jù)象限分別判斷曲線是凸的還是凹的,頭大啊酵紫。告嘲。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市奖地,隨后出現(xiàn)的幾起案子橄唬,更是在濱河造成了極大的恐慌,老刑警劉巖参歹,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仰楚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡犬庇,警方通過(guò)查閱死者的電腦和手機(jī)僧界,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)臭挽,“玉大人捎泻,你說(shuō)我怎么就攤上這事÷裼矗” “怎么了笆豁?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵郎汪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我闯狱,道長(zhǎng)煞赢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任哄孤,我火速辦了婚禮照筑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘦陈。我一直安慰自己凝危,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布晨逝。 她就那樣靜靜地躺著蛾默,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捉貌。 梳的紋絲不亂的頭發(fā)上支鸡,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音趁窃,去河邊找鬼牧挣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛醒陆,可吹牛的內(nèi)容都是我干的瀑构。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼刨摩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼寺晌!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起码邻,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎另假,沒(méi)想到半個(gè)月后像屋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡边篮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年己莺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片戈轿。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凌受,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出思杯,到底是詐尸還是另有隱情胜蛉,我是刑警寧澤挠进,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站誊册,受9級(jí)特大地震影響领突,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜案怯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一君旦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘲碱,春花似錦金砍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至离咐,卻和暖如春谱俭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宵蛀。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工昆著, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人术陶。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓凑懂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親梧宫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子接谨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容