iOS 一個好玩的加載動畫

之前看貼吧的加載動畫很有意思拿撩。就打算也做一個自定義的衣厘,最后的效果:

shuibolang3.gif

分層

首先要解決的問題是:怎么讓一個字體以中間上下層的顏色不同,并隨著波浪也會改變顏色压恒。

  • 第一個想法就是漸變層CAGradientLayer 影暴,CAGradientLayer可以做到讓一個字體上下層顏色變化,但是也無法做到隨著波浪的區(qū)域變化探赫,顏色也隨著變型宙,這個想法就給pass了。
  • 然后伦吠,就想到了之前做歌詞滾動的時候就可以讓歌詞的顏色隨時間滾動妆兑,原理是兩層label,改變外邊label層 mask的bounds 達到歌詞從左到右的滾動讨勤。mask層決定一個視圖的需要顯示的大小箭跳。博客鏈接:點我.
  • 這樣,變換個方向,就可以做到上下的分層顯示潭千。然后谱姓,開始思索怎么樣讓mask層顯示大小為波浪的大小,自然就想到了CAShapeLayer ∨偾纾現(xiàn)在做一個上下分層的
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(0, 0)];
        [path addLineToPoint:CGPointMake(0, w/2)];//w表示園的直徑
        [path addLineToPoint:CGPointMake(w, w/2)];
        [path addLineToPoint:CGPointMake(w, 0)];
        [path closePath];
        
        layer = [CAShapeLayer layer];
        layer.frame = label.bounds;
        layer.path = path.CGPath;
        layer.lineWidth = 1.f;
        layer.strokeColor = [UIColor greenColor].CGColor;
        
        //label是里面藍色背景白色字體屉来,label2是外面白色背景藍色字體.
        label2.layer.mask = layer;

效果:

平分.jpg

波浪動畫

接下來就可以畫波浪形了,有兩種方法狈癞,一種茄靠,用貝塞爾曲線。另一種用正弦函數(shù)(祭奠我那死去的數(shù)學知識),在看過daixunry(簡書作者)關于波浪的博客:點我蝶桶】考慮需要做波浪動畫 就用正弦函數(shù)去畫了。
下面照抄一下daixunry博客里面的一些函數(shù)解釋

正弦型函數(shù)解析式:y=Asin(ωx+φ)+h
各常數(shù)值對函數(shù)圖像的影響:
φ(初相位):決定波形與X軸位置關系或橫向移動距離(左加右減)
ω:決定周期(最小正周期T=2π/|ω|)
A:決定峰值(即縱向拉伸壓縮的倍數(shù))
h:表示波形在Y軸的位置關系或縱向移動距離(上加下減)
329672-d708b887c2bbf1ee.png

  大致就是在時間增加的時候把初相位往前或者往后移動,使得畫面看起來像波浪一樣脐雪。


329672-c5856d9bc788eb54.png

公式里面參數(shù)的設定

    1厌小、我們的容器高度是100,我希望波的整體高度战秋,固定在容器的一個相對的位置璧亚。
      這里設置h = 30;也就是說脂信,當Asin(ωx+φ)計算為0的時候癣蟋,這個時候y的位置是30;
    2狰闪、決定波起伏的高度疯搅,我們設置波峰是5,波峰越大尝哆,曲線越陡峭秉撇;
    3、決定波的寬度和周期秋泄,比如琐馆,我們可以看到上面的例子中是一個周期的波曲線,
      一個波峰恒序、一個波谷瘦麸,如果我們想在0到2π這個距離顯示2個完整的波曲線,那么周期就是π歧胁。
      我們這里設置波的寬度是容器的寬度_waveWidth滋饲,希望能展示2.5個波曲線,周期就是_waveWidth/2.5喊巍。
      那么ω常量就可以這樣計算:2.5*M_PI/_waveWidth屠缭。
    4、一共有兩個波曲線崭参,形成一個落差呵曹,也就是設置不同的φ(初相位),我們這里設置落差是M_PI/4何暮。
    5奄喂、時間和初相位的函數(shù)關系:我們在計時器的函數(shù)中一直調(diào)用_offset += _speed;
      可以看到,如果我們設置波的速度speed越大海洼,波的震動將會越快跨新。

    最后我們的公式如下:
    CGFloat y = _waveHeight*sinf(2.5*M_PI*i/_waveWidth + 3*_offset*M_PI/_waveWidth + M_PI/4) + _h;
    這些參數(shù)都可以自己調(diào)整,得到一個符合要求的效果坏逢。

現(xiàn)在來看代碼

//一些配置
        _waveWidth = w;//w位圓的直徑
        _waveHeight = 6;//振幅
        _h = w/2;//圓的中心
        _speed = 6.f;
- (void)wave
{
    _link = [CADisplayLink displayLinkWithTarget:self selector:@selector(doAni)];
    [_link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    
}

- (void)doAni
{
    //加減決定正反方向域帐,也可以speed為負的
    _offset += _speed;
    //設置第一條波曲線的路徑
    CGMutablePathRef pathRef = CGPathCreateMutable();
    //起始點
    CGFloat startY = _waveHeight*sinf(_offset*M_PI/_waveWidth) + _h;
    CGPathMoveToPoint(pathRef, NULL, 0, startY);
    //第一個波的公式
    for (CGFloat i = 0.0; i < _waveWidth; i ++) {
        CGFloat y = 1.1*_waveHeight*sinf(2*M_PI*i/_waveWidth + _offset*M_PI/_waveWidth) + _h;
        CGPathAddLineToPoint(pathRef, NULL, i, y);
    }
    //上邊是畫波浪線赘被,下邊是畫邊界,直接用直線就可以了
    CGPathAddLineToPoint(pathRef, NULL, _waveWidth, 0);
    CGPathAddLineToPoint(pathRef, NULL, 0, 0);
    CGPathCloseSubpath(pathRef);
    //設置第一個波layer的path
    layer.path = pathRef;
    layer.fillColor = [UIColor lightGrayColor].CGColor;
    CGPathRelease(pathRef);
}

先手動調(diào)用一次doAni

波浪.jpg

OK俯树,然后調(diào)用wave啟動計時器改變offset值就可以讓波浪形形成向前或向后移動的動畫帘腹。
bolang4.gif

現(xiàn)在波浪動畫完成了,字體的顏色也會隨波浪的動畫而改變许饿。這就完了嗎? 當然還沒有舵盈,仔細看貼吧的水波浪效果 會發(fā)現(xiàn)它還有一層立體效果陋率,使水波浪看起來有一種立體感。

立體感

在之前的基礎上思考如何再做出這一層立體感秽晚,很明顯的發(fā)現(xiàn)有兩層波浪瓦糟,兩個波浪重疊的部分的顏色會更藍色,字體顏色會偏灰色赴蝇。那我現(xiàn)在把下層的label也做一個波浪菩浙,兩個波浪重疊后鏤空的那部分就是要顯示立體效果。很簡單句伶,在底層再加一個label劲蜻, label的背景色和字體色就是你想要的立體效果。OK 這樣效果就完全達到了考余。

首先再填加一個label(深藍色背景,灰色字體,這里不貼代碼了)先嬉,然后先給下邊的label(藍色背景白色字體)添加一個layer 控制

        layer2 = [CAShapeLayer layer];
        layer2.frame = label.bounds;
        layer2.path = path.CGPath;
        layer2.strokeColor = [UIColor clearColor].CGColor;
        label.layer.mask = layer2;

然后在doAni里面添加一個label的路徑變化,在初相位上比上層的label快了M_PI/3

    //設置第二條波曲線的路徑
    CGMutablePathRef pathRef2 = CGPathCreateMutable();
    CGFloat startY2 = _waveHeight*sinf(_offset*M_PI/_waveWidth + M_PI/3)+_h;
    CGPathMoveToPoint(pathRef2, NULL, 0, startY2);
        //第二個波曲線的公式
    for (CGFloat i = 0.0; i < _waveWidth; i ++) {
        CGFloat y = 1.1 *_waveHeight*sinf(2*M_PI*i/_waveWidth + 1*_offset*M_PI/_waveWidth + M_PI/3) + _h;
        CGPathAddLineToPoint(pathRef2, NULL, i, y);
    }
    
    CGPathAddLineToPoint(pathRef2, NULL, _waveWidth, label.frame.size.height);
    CGPathAddLineToPoint(pathRef2, NULL, 0, label.frame.size.height);
    CGPathCloseSubpath(pathRef2);

    layer2.path = pathRef2;
    layer2.fillColor = [UIColor blackColor].CGColor;
    CGPathRelease(pathRef2);

最后來看看效果:

shuibolang3.gif

Demo項目地址:https://github.com/yxsufaniOS/SFWaterLoadingView

喜歡就收藏一下吧楚堤,謝謝疫蔓。

下面貼一下一些常用函數(shù)

算術函數(shù)
函數(shù)名 說明
int rand() 隨機數(shù)生成。 調(diào)用之前需要srand((unsigned)time(0));  //隨機數(shù)初期化身冬,不然隨機數(shù)不會變
int abs(int a) 整數(shù)的絕對值
double fabs(double a) 浮點數(shù)的絕對值
double floor(double a) 返回浮點數(shù)整數(shù)部分(舍棄小數(shù)點)
double ceil(double a) 返回浮點數(shù)整數(shù)部分(舍棄小數(shù)點部分衅胀,往個位數(shù)進1)
double pow(double a, double b) a的b次方
double sqrt(double a) a的平方根
三角函數(shù)
函數(shù)名 說明
double cos(double a) 余弦函數(shù) (a:弧度)
double sin(double a) 正弦函數(shù)∷煮荨(a:弧度)
double tan(double a) 正切函數(shù)」銮(a:弧度)
double asin(double a) 反正弦值 (a:弧度)
double acos(double a) 反余弦函數(shù)(a:弧度)
double atan(double a) 反正切函數(shù)
double atan2(double a, double b) 返回給定的 a 及 b 坐標值的反正切值
指數(shù)函數(shù)
函數(shù)名 說明
double log(double a) 以e 為底的對數(shù)值
double log10(double a) 對數(shù)函數(shù)log
常數(shù)
常數(shù)名 說明
M_PI 圓周率(=π)
M_PI_2 圓周率的1/2(=π/2)
M_PI_4 圓周率的1/4(=π/4)
M_1_PI =1/π
M_2_PI =2/π
M_E =e
M_LOG2E log_2(e)
M_LOG10E log_10(e)
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末樱哼,一起剝皮案震驚了整個濱河市哀九,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌搅幅,老刑警劉巖阅束,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異茄唐,居然都是意外死亡息裸,警方通過查閱死者的電腦和手機蝇更,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呼盆,“玉大人年扩,你說我怎么就攤上這事》闷裕” “怎么了厨幻?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長腿时。 經(jīng)常有香客問我况脆,道長,這世上最難降的妖魔是什么批糟? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任格了,我火速辦了婚禮,結(jié)果婚禮上徽鼎,老公的妹妹穿的比我還像新娘盛末。我一直安慰自己,他們只是感情好否淤,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布悄但。 她就那樣靜靜地躺著,像睡著了一般叹括。 火紅的嫁衣襯著肌膚如雪算墨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天汁雷,我揣著相機與錄音净嘀,去河邊找鬼。 笑死侠讯,一個胖子當著我的面吹牛挖藏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播厢漩,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼膜眠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了溜嗜?” 一聲冷哼從身側(cè)響起宵膨,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炸宵,沒想到半個月后辟躏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡土全,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年捎琐,在試婚紗的時候發(fā)現(xiàn)自己被綠了会涎。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡瑞凑,死狀恐怖末秃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情籽御,我是刑警寧澤练慕,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站技掏,受9級特大地震影響贺待,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜零截,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望秃臣。 院中可真熱鬧涧衙,春花似錦、人聲如沸奥此。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稚虎。三九已至撤嫩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蠢终,已是汗流浹背序攘。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寻拂,地道東北人程奠。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像祭钉,于是被迫代替她去往敵國和親瞄沙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

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

  • 前言:關于貝塞爾曲線與CAShapeLayer的學習 學習Demo演示: 貝塞爾曲線簡單了解 使用UIBezier...
    麥穗0615閱讀 17,870評論 18 149
  • 在iOS中隨處都可以看到絢麗的動畫效果慌核,實現(xiàn)這些動畫的過程并不復雜距境,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,485評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果垮卓,實現(xiàn)這些動畫的過程并不復雜垫桂,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,110評論 5 13
  • 遠古時期扒接,天地茫茫伪货,宇宙洪荒们衙,人民飽受洪災之苦。當時的清音谷(即現(xiàn)在的西應)月灣山方向沒有出口碱呼,所以整個清音谷是一...
    哈士奇2016閱讀 213評論 0 0
  • 時間過得真快蒙挑,一晃半年過去了
    common_hycs閱讀 126評論 0 0