【算法分析】QQ“一鍵退朝”之詳細計算方法

Tips:由于簡書好像不支持Latex公式,所以為了效果,有關(guān)公式部分截取了我發(fā)表在CSDN上的博文,地址:AZZ的博客


相信很多朋友和我一樣很喜歡QQ上“一鍵退朝”的功能,就是把紅點從它原本的地方拉走,消息提醒也就沒有了。

一鍵退朝功能示意圖

直到如今我還是覺得這個功能很酷炫!于是想自己實現(xiàn)一番,經(jīng)過一番調(diào)查知道拉伸其實就是由兩個圓加上兩條貝塞爾曲線組成的形狀。

來看看騰訊設(shè)計師是怎么設(shè)計出來的吧:《QQ手機版 5.0“一鍵下班”設(shè)計小結(jié)》

看完了這個對實現(xiàn)思路有很大的幫助,可是我還是不能知道具體是怎么計算實現(xiàn)的,網(wǎng)上大部分的教程都是假想成了兩個同樣大小的圓來計算,這太取巧了!因為同樣大小的圓兩條外公切線是平行的,同一個圓上的公切點相連是會垂直于連心線的,但是大小不同的圓并沒有這個特殊性!

另外網(wǎng)上也有很多仿照的項目,可是看算法看得頭都大了也不明白為什么是這樣算的!經(jīng)過兩天的研究,把初中數(shù)學(xué)(圓、三角函數(shù)等相關(guān)知識)好好復(fù)習(xí)了一遍,終于搞清楚了其中算法,現(xiàn)在跟我一起來看看吧!


1.得到連心線


通過觀察可以發(fā)現(xiàn),在“一鍵退朝”這個功能當(dāng)中,有一個小圓固定在原來坐標位置不動的,只是半徑會發(fā)生變化,另一個大圓是跟隨著我們手指滑動到屏幕的位置來確定圓心坐標的,一般大圓的半徑是固定的。

建立兩圓的相對坐標系:

PS:在移動端的坐標系 y 軸是向下的。

假設(shè)某一個時刻,兩圓的狀態(tài)如圖,我們現(xiàn)在可以確定的是小圓的圓心坐標 O 為(startX, startY),大圓的圓心坐標 P0 為 (x0, y0),以及小圓的半徑 r 和大圓的半徑 R 。

那么首先可以把連心線求出來!也就是 O P0 的距離。


2.求切點坐標

復(fù)習(xí)一下初中數(shù)學(xué):

兩個外離的圓,一定有兩條外公切線。若兩圓半徑相同,則兩外公切線平行;否則相交于一點,且該點與兩圓心在同一直線。

我們再作一張有公切線的圖:

切點為 P1、P2、P3、P4,我們現(xiàn)在目的就要求出這四個點,然后就能夠在程序中畫出切線。

整個算法最難的地方恐怕就是求這四個點了,我們需要借助作圖來幫助計算,這之前還需要先復(fù)習(xí)下定理:

圓心和切點的連線一定垂直于過該點的公切線

再作幾個輔助點 A、B、C、D,AB 表示以大圓圓心為原點的坐標系的 x 軸的兩端,CD 表示以小圓圓心為原點的坐標系的 x 軸的兩端,

3.求剩下兩個切點的坐標

一開始我以為 P3、P4 的算法和 P1、P2 一樣,就是把上面的減號換成加號就可以了??墒呛髞眚炞C后發(fā)現(xiàn)不對, P3、P4 不能直接使用 β 進行運算。

?為了能愉快閱讀,再來復(fù)習(xí)一下各種拉丁希臘符號叫法:

?α 阿爾法 β 貝塔 γ 伽瑪 δ 德爾塔 ε 伊普西隆 ζ 澤塔

如上圖作輔助線。

4.畫貝塞爾曲線


把四個切點坐標求出來了,后面就簡單了,現(xiàn)在就是以切線為原軸,畫貝塞爾曲線了,不過我們還缺少一個控制點的坐標。

4.1 科普貝塞爾


怕有不清楚貝塞爾曲線的朋友,我科普一下先,簡單來說就是求一段平滑曲線的公式。

如果我們把畫一條直線分為進度100%的話,那么當(dāng)進度為0%,12%,58%,74%時,畫線的狀態(tài)為(注意紅色部分末的黑色端點,灰色部分為路徑指示)


那么把所有時刻的黑點連接起來就構(gòu)成了直線:


這個概念應(yīng)該比較容易接受,好了繼續(xù)。

二次貝塞爾曲線(最簡單的貝塞爾曲線)的作法首先需要兩個點確定一條直線,另外在直線外確定一點(即控制點),然后此時三點會形成三個線段,即下圖的P0 P2、P0 P1和 P1 P2$(其實不用關(guān)注 P0 P2)

這只是進度為0時候的狀態(tài),按照上面概念,當(dāng)進度 t 從 0 變化到 100 時的某一個時刻,比如 30, 66 ,99,那么各個時刻 P0 P1 和 P1 P2 的狀態(tài)為

t=30


t=66
t=99

可以發(fā)現(xiàn),在 P0 P1 和 P1 P2 上有一直運動的兩個點,我們將這兩個點連接起來又形成一段新的線段,而在不同時刻,在這個新線段上同樣會有一個運動的點,這個點也遵守 t 的變化。


t=30
t=66
t=99

把所有時刻的黃色點連接起來,就形成了二階貝塞爾曲線。

還不能理解的可以看下這個視頻 - > 《bezier curve原理》- > 只要看就好,聽不懂英文的可以把聲音關(guān)掉。


bezier curve原理

費這么大勁把二階貝塞爾講了一遍,我們這里其實也只用到了二階,高階我就不講了,一通百通。

4.2.尋找控制點


那么現(xiàn)在線段已經(jīng)能確定了,就是兩條公切線線段(P1P2、P3P4),那么控制點在哪呢?

這個其實有點靠猜了=。= 一開始我覺得應(yīng)該在連心線的中點,其實實現(xiàn)后效果也還行,后來參照騰訊設(shè)計師的想法效果更好,他令 P1P2 的控制點為 P1P4 的中點,令 P3P4 的控制點為 P2P3 的中點。

軟件實現(xiàn)效果對比(上邊控制點是連心線的中點,下邊是騰訊設(shè)計師提出的控制點):


我個人覺得下邊效果更好,也不得不佩服TX設(shè)計師的聰明才智,讓我自己想可能永遠也想不到。

至于求 P1P4 和? P2P3 的中點不難吧?連四個坐標點都求出來了,直接算就可以了!

---

源碼地址:https://github.com/Xieyupeng520/AZMetaBall(還會不斷完善的,求星星^3^)


---

References:

《QQ手機版 5.0“一鍵下班”設(shè)計小結(jié)》

《【Android開源項目解析】QQ“一鍵下班”功能實現(xiàn)解析——學(xué)習(xí)Path及貝塞爾曲線的基本使用》

[Github - MetaballLoading]

本教程為了方便講解有篡改原圖,還望原圖作者見諒!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容