最近遇到了水波波動的動畫效果鞭光,看書資料學習下氧敢,做了個小demo啰脚,希望別人有所幫助庆冕。
這里我是用CAShapeLayer來實現(xiàn)水波動畫的参淫,而不是使用Core Graphics直接向原始的CALyer的內容中繪制一個路徑,主要還是CAShapeLayer有更多的優(yōu)點的:
? 渲染快速愧杯。CAShapeLayer使用了硬件加速涎才,繪制同一圖形會比用Core Graphics快很多。
? 高效使用內存力九。一個CAShapeLayer不需要像普通CALayer一樣創(chuàng)建一個寄宿圖形耍铜,所以無論有多大,都不會占用太多的內存跌前。
? 不會被圖層邊界剪裁掉棕兼。一個CAShapeLayer可以在邊界之外繪制。你的圖層路徑不會像在使用Core Graphics的普通CALayer一樣被剪裁掉抵乓。
? 不會出現(xiàn)像素化伴挚。當你給CAShapeLayer做3D變換時,它不像一個有寄宿圖的普通圖層一樣變得像素化灾炭。
首先創(chuàng)建一個CAShapeLayer:
//新建一個形狀圖層
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
//圖形填充的顏色
shapeLayer.fillColor = [[UIColor colorWithRed:86/255.0f green:202/255.0f blue:139/255.0f alpha:0.3] CGColor];
//圖形線的寬度
shapeLayer.lineWidth = 1;
//圖形線(邊界)的顏色
shapeLayer.strokeColor = [[UIColor colorWithRed:86/255.0f green:202/255.0f blue:139/255.0f alpha:0.3] CGColor];
//添加形狀圖層
[self.view.layer addSublayer:shapeLayer];
self.shapeLayer = shapeLayer;
我們先分析一下水波動畫:
wave.gif
通過觀察我們可以看到水波動畫我們要實現(xiàn)頂部的線條進行上下凹凸茎芋、平行移動,通俗來講就是一條移動的波浪線(~),那怎么才能不斷的畫對稱的波浪線蜈出,我們回憶下我們學過的數(shù)學知識便可以發(fā)現(xiàn)我們高中學習的正弦函數(shù)和余弦函數(shù)是最相符的田弥,這里我選擇用正弦函數(shù)來做,首先復習一些正弦函數(shù)的信息铡原;
y=sin(x);這是最基本的正弦函數(shù)周期為2π偷厦,y的最值是±1,顯然y的最值對我們意義不大燕刻,那我們考慮正線性函數(shù)
y=Asin(ωx+φ)+h 在表達式中 A 表示振幅只泼,也就是使用這個變量來調整波浪的高度 ω表示周期,也就是使用這個變量來調整在屏幕內顯示的波浪的數(shù)量 φ表示波浪橫向的偏移卵洗,也就是使用這個變量來調整波浪的流動 h表示波浪縱向的位置请唱,也就是使用這個變量來調整波浪在屏幕中豎直的位置。
通過上面的函數(shù)忌怎,我們就能計算出波浪曲線上任意位置的坐標點籍滴,把這些點點連起來便可得到一條我們需要的曲線
//繪制圖層的路徑
CGMutablePathRef wavePath = CGPathCreateMutable();
//繪制路徑的起始位置
CGPathMoveToPoint(wavePath, nil, 0, self.waterWaveHeight);
CGFloat y = 0.f;
//y=Asin(ωx+φ)+h
//路徑最大的寬度,屏幕的寬度
CGFloat pathWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat pathheight = [UIScreen mainScreen].bounds.size.height;
//畫點
for (float x = 0.0; x <= pathWidth; x++) {
y = 10*self.height_Y * sin((x/180*M_PI) - 2*(self.offset_X/M_PI)) + self.waterWaveHeight;
CGPathAddLineToPoint(wavePath, nil, x, y);
}
//將圖像的四個點連起來形成閉合圖形
CGPathAddLineToPoint(wavePath, nil, pathWidth, pathheight);
CGPathAddLineToPoint(wavePath, nil, 0, pathheight);
CGPathAddLineToPoint(wavePath, nil, 0, self.waterWaveHeight);
//結束繪圖信息
CGPathCloseSubpath(wavePath);
self.shapeLayer.path = wavePath;
//釋放繪圖路徑
CGPathRelease(wavePath);
下面我們要讓這條線自動的動起來榴啸,這里不要使用NSTimer
孽惰,因為使用NSTimer
會有卡頓感,我們創(chuàng)建一個和屏幕刷新頻率相同的計時器:CADisplayLink
鸥印,并將它加到RunLoop
里
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(creatAnimationPath)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
每次屏幕刷新時都會執(zhí)行這個方法
- (void)creatAnimationPath{
self.offset_X += 0.1;
[self craetWavePath];
}
到這我們就實現(xiàn)了一個水波動畫勋功,文章介紹的是實現(xiàn)的思路坦报,代碼會比較散;demo已經上傳可下載代碼查看具體的實現(xiàn):水波動畫--GitHub