由于前段時(shí)間發(fā)現(xiàn)自己在Github上的這份代碼被簡(jiǎn)書上某用戶直接拷貝來發(fā)表了,而又并沒有注明代碼出處,于是決定還是自己著手寫一篇好了。
先看一下最終效果圖:

首先我們可以把如此絲滑的水波紋拆分一下下:
- 一條規(guī)律的曲線。
- 曲線勻速向右移動(dòng)。
- 曲線下方的位置用顏色填充。
于是先來一條曲線吧。
對(duì)于需要產(chǎn)生波動(dòng)如此規(guī)律的曲線,我們首先想到的應(yīng)該就是三角函數(shù)了。
例如我們熟悉的正弦曲線:

及其公式:
f(x) = Asin(ωx+φ)+k
而SDK也為我們提供了這個(gè)正弦函數(shù):
extern double sin(double);
于是乎通過一個(gè)循環(huán)就能輕易地獲取到這條曲線了:
CGFloat y = 0.f;
for (CGFloat x = 0.f; x <= CGRectGetWidth(self.frame) ; x++) {
y = height * sin(self.angularSpeed * x + self.offsetX);
CGPathAddLineToPoint(path, NULL, x, y);
}
讓它動(dòng)起來
我們需要在屏幕每次刷新的時(shí)候進(jìn)行一次曲線的繪制,讓它不斷地刷新。
self.waveDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(currentWave)];
而根據(jù)上面的正弦函數(shù)公式,曲線要向右移,其φ值就需要變小。于是在 currentWave 方法每次調(diào)用的時(shí)候,offsetX均減去同一個(gè)固定值,以實(shí)現(xiàn)勻速的運(yùn)動(dòng)。
self.offsetX -= self.waveSpeed;
涂個(gè)顏色
連個(gè)線,形成封閉空間:
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 0, height / 2);
CGFloat y = 0.f;
for (CGFloat x = 0.f; x <= CGRectGetWidth(self.frame) ; x++) {
y = height * sin(self.angularSpeed * x + self.offsetX);
CGPathAddLineToPoint(path, NULL, x, y);
}
CGPathAddLineToPoint(path, NULL, width, height);
CGPathAddLineToPoint(path, NULL, 0, height);
CGPathCloseSubpath(path);
再填個(gè)色:
self.waveShapeLayer.fillColor = self.waveColor.CGColor;
好了。
至于最后的漸變消失略簡(jiǎn)單就不說了。有興趣的直接到文末下載完整代碼吧~
多扯兩句
這水波紋并不限定在拖動(dòng)過后才能波動(dòng),而是隨時(shí)想動(dòng)就動(dòng)、想停就停。
于是最近我想到了一些新玩法,例如用作刷新等待視圖。

更多的玩法就自行發(fā)掘吧~
最后
完整代碼呈上:
其使用方法在該頁(yè)面中會(huì)有介紹。
喜歡的歡迎給個(gè)star~玩得開心哈。