【iOS】基于UIScrollView實(shí)現(xiàn)的圓環(huán)轉(zhuǎn)盤效果

演示案例 - 關(guān)系星球

實(shí)現(xiàn)效果:

需求背景

單個(gè)星球會(huì)有0~15個(gè)關(guān)系用戶,每個(gè)用戶以星球中點(diǎn)為圓心環(huán)繞擺放褪猛,星球只展示一半网杆,并且能上下拖動(dòng)查看更多用戶,如圖所示:

實(shí)現(xiàn)方案

1. 坐標(biāo)計(jì)算

從設(shè)計(jì)圖可得知伊滋,半邊星球最多展示6個(gè)用戶碳却,一圈360°,半圈180°笑旺,也就是多個(gè)用戶依次相隔30°環(huán)繞星球中心擺放昼浦。

已知圓心、半徑筒主、每個(gè)用戶的弧度关噪,通過三角函數(shù)就可以計(jì)算出每個(gè)用戶的(初始)坐標(biāo)了:

let centerX: CGFloat = circlePoint.x + radius * cos(radian)
let centerY: CGFloat = circlePoint.y + radius * sin(radian)

2. 手指轉(zhuǎn)動(dòng)

現(xiàn)在每個(gè)用戶的位置都可以確定了,還需要通過手指進(jìn)行轉(zhuǎn)動(dòng)物舒。

既然是用手指進(jìn)行轉(zhuǎn)動(dòng)色洞,是不是加個(gè)UIPanGestureRecognizer然后改變弧度就可以實(shí)現(xiàn)轉(zhuǎn)動(dòng)了呢?

是可以冠胯,只不過只能單純轉(zhuǎn)動(dòng)火诸,沒有任何慣性,效果很是生硬荠察,雖然也可以通過一些數(shù)學(xué)公式實(shí)現(xiàn)慣性效果置蜀,不過對(duì)于我來說過于復(fù)雜且不好控制,所以作罷悉盆。

UIKit里面有沒有這種慣性拖動(dòng)的控件呢盯荤?--- 很明顯,UIScrollView自帶慣性效果焕盟,這能滿足我的需求秋秤。

首先,想要UIScrollView能夠拖動(dòng)脚翘,就得設(shè)置一個(gè)比它自身Size還要大的contentSize灼卢,至于要設(shè)置多高的contentSize(這里需求是垂直方向,因此只需要設(shè)置contentSize.height即可)才合適呢来农?

由設(shè)計(jì)圖可得知鞋真,星球一圈最多12個(gè),半圈則是6個(gè)沃于,也就是說涩咖,contentSize.height等于1個(gè)星球高度時(shí)可容納6個(gè)用戶海诲,等于2個(gè)星球高度可容納12個(gè)用戶,也就是剛好容納一圈用戶所需的內(nèi)容高度檩互。所以平均一個(gè)用戶占用內(nèi)容高度為planet.height / 6特幔,很好,這樣不管有多少個(gè)用戶盾似,都可以動(dòng)態(tài)設(shè)置contentSize.height了敬辣。

contentSize.height = (planet.height / 6) * CGFloat(peopleViews.count)

確定好contentSize.height了,接下來該如何通過拖拽進(jìn)行轉(zhuǎn)動(dòng)呢零院?

既然已經(jīng)知道了容納一圈用戶所需的內(nèi)容高度溉跃,也知道了一個(gè)用戶的占用內(nèi)容高度和角度,那就可以根據(jù)當(dāng)前偏移量容納一圈用戶的內(nèi)容高度告抄,算出轉(zhuǎn)動(dòng)百分比撰茎,有了這個(gè)轉(zhuǎn)動(dòng)百分比,去刷新所有用戶的當(dāng)前轉(zhuǎn)動(dòng)位置了打洼。

let radian360 = CGFloat.pi * 2
let radian90 = CGFloat.pi / 2
let singlePeopleRadian = radian360 / 12.0

let oneRoundContentHeight = planet.frame.height * 2
let offsetY = scrollView.contentOffset.y
let progress = offsetY / oneRoundContentHeight

peopleViews.forEach { peopleView in
    let index = peopleView.tag
    
    // 弧度
    var radian: CGFloat = singlePeopleRadian * CGFloat(index) - radian90 // iOS的0°為水平位置龄糊,-90°為了回去會(huì)垂直位置
    radian -= progress * radian360 // 逆時(shí)針轉(zhuǎn)動(dòng),相減
    
    // 中點(diǎn)
    let centerX: CGFloat = circlePoint.x + radius * cos(radian)
    let centerY: CGFloat = circlePoint.y + radius * sin(radian)
    
    // 加上offsetY是為了讓所有用戶轉(zhuǎn)動(dòng)時(shí)能保持在scrollView的顯示區(qū)域內(nèi)
    peopleView.center = CGPoint(x: centerX, y: offsetY + centerY)
}

其他需求

有了這個(gè)轉(zhuǎn)動(dòng)百分比募疮,剩下的需求就很容易實(shí)現(xiàn)了炫惩,例如控制名字的漸變顯示、只顯示右半屏的用戶等阿浓,這些都是給定一個(gè)限值他嚷,然后根據(jù)百分比慢慢刷新的事情,這里就不贅述了芭毙。

優(yōu)化

  1. 復(fù)用機(jī)制【已實(shí)現(xiàn)】:從視覺上筋蓖,一個(gè)屏幕也就最多顯示6~7個(gè)關(guān)系用戶,那就可以參考UITableView的做法退敦,使用一個(gè)集合當(dāng)作關(guān)系用戶的緩存池粘咖,轉(zhuǎn)動(dòng)過程中,但轉(zhuǎn)出顯示范圍(半屏)就把該視圖丟進(jìn)緩存池侈百,然后下一個(gè)用戶即將顯示時(shí)則從緩存池里取出來瓮下。最多只需要?jiǎng)?chuàng)建8個(gè)關(guān)系用戶視圖,即可實(shí)現(xiàn)無數(shù)個(gè)用戶的轉(zhuǎn)動(dòng)效果钝域,大大減少CPU的計(jì)算量讽坏。
  1. 動(dòng)態(tài)插入/刪除【未實(shí)現(xiàn)】:如果用整體刷新的動(dòng)畫來進(jìn)行插入/刪除,更新只會(huì)以兩個(gè)用戶之間的直線軌跡進(jìn)行位移動(dòng)畫网梢,這不符合轉(zhuǎn)盤的形式震缭,需加入圓弧動(dòng)畫赂毯,目前暫未實(shí)現(xiàn)战虏,將日后提供拣宰。

Demo

下載地址:TurntableView-Demo

  • ??提供了調(diào)試功能,以便更好理解烦感。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末巡社,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子手趣,更是在濱河造成了極大的恐慌晌该,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绿渣,死亡現(xiàn)場(chǎng)離奇詭異朝群,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)中符,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門姜胖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人淀散,你說我怎么就攤上這事右莱。” “怎么了档插?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵慢蜓,是天一觀的道長。 經(jīng)常有香客問我郭膛,道長晨抡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任饲鄙,我火速辦了婚禮凄诞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘忍级。我一直安慰自己帆谍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布轴咱。 她就那樣靜靜地躺著汛蝙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪朴肺。 梳的紋絲不亂的頭發(fā)上窖剑,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音戈稿,去河邊找鬼西土。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鞍盗,可吹牛的內(nèi)容都是我干的需了。 我是一名探鬼主播跳昼,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼肋乍!你這毒婦竟也來了鹅颊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤墓造,失蹤者是張志新(化名)和其女友劉穎堪伍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體觅闽,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帝雇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛉拙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摊求。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖刘离,靈堂內(nèi)的尸體忽然破棺而出室叉,到底是詐尸還是另有隱情,我是刑警寧澤硫惕,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布茧痕,位于F島的核電站,受9級(jí)特大地震影響恼除,放射性物質(zhì)發(fā)生泄漏踪旷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一豁辉、第九天 我趴在偏房一處隱蔽的房頂上張望令野。 院中可真熱鬧,春花似錦徽级、人聲如沸气破。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽现使。三九已至,卻和暖如春旷痕,著一層夾襖步出監(jiān)牢的瞬間碳锈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工欺抗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留售碳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像贸人,于是被迫代替她去往敵國和親竿屹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

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