iOS--如何寫一個微博導航欄動畫(CoreGraphics)

前言

昨天剛做完項目的新版本、除了嘗試一些新的架構之外、功能方面并沒什么特別的地方掏婶。
但是順手搞了一些還算好玩的東西、其一就是這個導航欄的動畫潭陪。
感覺還算簡單易懂雄妥、分享一下(其實更多是最近攢了好多封面、不貼出來憋得人難受)依溯。

導航欄動畫.gif

思路

先介紹CA的兩個方法:
  • 基于原始狀態(tài)的位移
CG_EXTERN CGAffineTransform CGAffineTransformMakeTranslation(CGFloat tx,
  CGFloat ty) CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
  • 基于原始狀態(tài)的形變
CG_EXTERN CGAffineTransform CGAffineTransformScale(CGAffineTransform t,
  CGFloat sx, CGFloat sy) CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

知道了這兩個方法老厌、剩下就是如何使用形變和位移以達到想要的效果了。

這里黎炉、需要分兩部分來看枝秤、一部分是位移、一部分是形變
而且慷嗜、如果將一整個動畫以及翻頁動作看成1淀弹。那么位移和形變又需要分成兩部分來看:0到0.5以及0.5到1丹壕。

其實一點都不難、畫個圖看一眼垦页。連一元方程都不算雀费、完全是小學算術題~甚至連奧數(shù)都算不上。

0到0.5區(qū)間內

  • 先看形變

在0.5時痊焊、我們需要將線條長度從left_width形變成max_width

形變-0到0.5

  • 再看位移

與此同時如果想讓線條在左側看起來并沒有移動盏袄、就需要將線條的x軸一點點向右移動。這個移動的值呢?
由于形變是雙向的薄啥、右側和左側都會變長辕羽。那么對于左側最終將是中間時最終形變差值的一半。
具體到數(shù)值:
最左側到中心點時x軸的位移 = 最左側到中心點時形變的差值/2 = (max_width - left_width)/2

0.5到1區(qū)間內

  • 依舊先看形變

和之前的形變相同


形變-0.5到1
  • 然后來看位移

同理垄惧、如果我的長度減少了X刁愿、那么我如果想保證看起來右側位置不會改變、考慮到形變是左右同時發(fā)生到逊、就需要向右移動X/2铣口。
具體到數(shù)值:
中心點到最右側時x軸的位移 = 中心點到最右時形變的差值/2 = (max_width - right_width)/2


具體函數(shù)

以我項目里兩個按鈕(self.titleBtn1/self.titleBtn2)為例

if (0 <= offsetRate && offsetRate <= 0.5) {
        /*
         * 左側與中間相互移動
         */
        
        //x軸位移 :: 中間時位移 * 偏移比例系數(shù)
        CGFloat translationOfX = _translationofX_center * offsetRate * 2;
        self.line.transform = CGAffineTransformMakeTranslation(translationOfX, 0);
        
        //x軸形變 :: 1 + (最大時相對形變) * 偏移比例系數(shù)
        CGFloat flagScale = 1 + (_flagScale_center - 1) * (offsetRate * 2);
        self.line.transform = CGAffineTransformScale(self.line.transform, flagScale, 1);
        
    }else if (0.5 < offsetRate && offsetRate <= 1) {
        /*
         * 中間與右側相互移動
         */
        
        //x軸位移 :: 中間時位移 + 最終位移 * 偏移比例系數(shù)
        CGFloat translationOfX = _translationofX_center + _translationofX_right * (offsetRate - 0.5) * 2;
        self.line.transform = CGAffineTransformMakeTranslation(translationOfX, 0);
        
        //x軸形變 :: 最大時形變 - (最大形變 - 最終形變) * 偏移比例系數(shù)
        CGFloat flagScale = _flagScale_center - (_flagScale_center - _btn2Width/_btn1Width) * (offsetRate - 0.5) * 2;

        self.line.transform = CGAffineTransformScale(self.line.transform, flagScale, 1);
    }

其中的某些參數(shù)的意義以及取值:

{
    //整體最大寬度
    CGFloat _maxWidth;
    //位于左側時寬度
    CGFloat _btn1Width;
    //位于右側時寬度
    CGFloat _btn2Width;
    //從左側移到中心時x軸位移
    CGFloat _translationofX_center;
    //從中心移到右側時x軸位移
    //所以總位移就是_translationofX_center+_translationofX_right
    CGFloat _translationofX_right;
    //位于中心時形變
    CGFloat _flagScale_center;
}

{
    _btn1Width = self.titleBtn1.width;
    _btn2Width = self.titleBtn2.width;
    _maxWidth = self.titleBtn2.right - self.titleBtn1.left;
    _translationofX_center = (_maxWidth - _btn1Width)/2;
    _translationofX_right = (_maxWidth - _btn2Width)/2;
    _flagScale_center = _maxWidth/_btn1Width;
    self.line.frame = CGRectMake(self.titleBtn1.left, self.height, self.titleBtn1.width, 1);
}

將屏幕滑動的偏移量傳遞進來

#pragma mark UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    CGFloat offsetX = scrollView.contentOffset.x;
    CGFloat offsetRate = offsetX/BSScreen_Width;
    

    //將偏移率傳遞給navView
    
    [self.navView configLingWithOffsetRate:offsetRate];

}


Demo

上面的例子的代碼其實都已經(jīng)列出來了、沒什么再單獨傳Demo的必要觉壶。
但是畢竟開了個帖子脑题、連個Demo都沒有不好看。于是上午干脆封裝了一個小工具出來铜靶。
但是只封裝了移動的動畫叔遂、并沒封裝按鈕變色等等一系列功能。

KTNavDemo.gif

用起來也挺簡單的争剿、只要將按鈕的數(shù)組已艰、下方橫線交付、在屏幕滑動的時候把偏移量傳遞進去蚕苇、就能自動工作了哩掺。寬度啊什么都會自己算:

@interface KTNavScrollTool : NSObject


/**
 初始化

 @param titleArr 按鈕數(shù)組
 @param line 需要移動的橫線
 @return 實例對象
 */
- (instancetype)initWithTitleArr:(NSArray<UIView *> *)titleArr line:(UIView *)line;


/**
 移動的函數(shù)

 @param offsetRate scrollview滾動式的偏移量的比例
 */
- (void)configLingWithOffsetRate:(CGFloat)offsetRate;
@end

GitHub有興趣可以自取

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市涩笤,隨后出現(xiàn)的幾起案子疮丛,更是在濱河造成了極大的恐慌,老刑警劉巖辆它,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異履恩,居然都是意外死亡锰茉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門切心,熙熙樓的掌柜王于貴愁眉苦臉地迎上來飒筑,“玉大人片吊,你說我怎么就攤上這事⌒牛” “怎么了俏脊?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肤晓。 經(jīng)常有香客問我爷贫,道長,這世上最難降的妖魔是什么补憾? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任漫萄,我火速辦了婚禮,結果婚禮上盈匾,老公的妹妹穿的比我還像新娘腾务。我一直安慰自己,他們只是感情好削饵,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布岩瘦。 她就那樣靜靜地躺著,像睡著了一般窿撬。 火紅的嫁衣襯著肌膚如雪启昧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天尤仍,我揣著相機與錄音箫津,去河邊找鬼。 笑死宰啦,一個胖子當著我的面吹牛苏遥,可吹牛的內容都是我干的。 我是一名探鬼主播赡模,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼田炭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了漓柑?” 一聲冷哼從身側響起教硫,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辆布,沒想到半個月后瞬矩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡锋玲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年景用,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惭蹂。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡伞插,死狀恐怖割粮,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情媚污,我是刑警寧澤舀瓢,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站耗美,受9級特大地震影響京髓,放射性物質發(fā)生泄漏。R本人自食惡果不足惜幽歼,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一朵锣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甸私,春花似錦诚些、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至弃鸦,卻和暖如春绞吁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背唬格。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工家破, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人购岗。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓汰聋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親喊积。 傳聞我的和親對象是個殘疾皇子烹困,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348