簡介
使用iOS原生CoreGraphic框架完成,主要內容就是在給定的路徑上繪制出圖形,水波紋的實現是按照三角函數的sin函數來實現的,利用sin函數計算出大量的點,然后做顏色填充。
實現方法
首先一個波紋需要一個layer來進行渲染,越底層的波紋要越早繪制,本Demo只實現了雙波紋交錯。
水波紋基本屬性:
不需要對外暴露的屬性
@interface WaterRippleView(){
float _currentLinePointY;
}
@property (nonatomic, strong)CADisplayLink *rippleDisplayLink;//蘋果的垂直同步
@property (nonatomic, strong)CAShapeLayer *mainRippleLayer;//主波圖層
@property (nonatomic, strong)CAShapeLayer *minorRippleLayer;//次波圖層
@property (nonatomic, assign)CGFloat rippleWidth;//波浪寬度
@end
可以對外暴露的屬性
@property (nonatomic, strong)UIColor *mainRippleColor;//主波填充顏色
@property (nonatomic, strong)UIColor *minorRippleColor;//次波填充顏色
@property (nonatomic, assign)CGFloat mainRippleoffsetX;//主波偏移量
@property (nonatomic, assign)CGFloat minorRippleoffsetX;//次波偏移量
@property (nonatomic, assign)CGFloat rippleSpeed;//波浪速度
@property (nonatomic, assign)CGFloat ripplePosition;//波浪Y軸位置
@property (nonatomic, assign)float rippleAmplitude;//波浪振幅
各屬性的默認值設置
self.mainRippleColor = [UIColor colorWithRed:255/255.0f green:127/255.0f blue:80/255.0f alpha:1];
self.minorRippleColor = [UIColor whiteColor];
self.mainRippleoffsetX = 1;
self.minorRippleoffsetX = 2;
self.rippleSpeed = .5f;
self.rippleWidth = frame.size.width;
self.ripplePosition = frame.size.height-10.0f;
self.rippleAmplitude = 5;
對外暴露的方法
//設置frame 主波填充顏色 次波填充顏色
- (instancetype)initWithFrame:(CGRect)frame mainRippleColor:(UIColor *)mainRippleColor minorRippleColor:(UIColor *)minorRippleColor;
//設置frame 主波填充顏色 次波填充顏色 主波偏移量 次波偏移量 波浪速度 波浪Y軸位置 波浪振幅
- (instancetype)initWithFrame:(CGRect)frame mainRippleColor:(UIColor *)mainRippleColor minorRippleColor:(UIColor *)minorRippleColor mainRippleoffsetX:(float)mainRippleoffsetX minorRippleoffsetX:(float)minorRippleoffsetX rippleSpeed:(float)rippleSpeed ripplePosition:(float)ripplePosition rippleAmplitude:(float)rippleAmplitude;
在view中需要繪制圖形時,要在自帶的dramRect:方法中編寫相關代碼
- (void)drawRect:(CGRect)rect {
/*
*創建兩個layer
*/
self.mainRippleLayer = [CAShapeLayer layer];
self.mainRippleLayer.fillColor = self.mainRippleColor.CGColor;
[self.layer addSublayer:self.mainRippleLayer];
self.minorRippleLayer = [CAShapeLayer layer];
self.minorRippleLayer.fillColor = self.minorRippleColor.CGColor;
[self.layer addSublayer:self.minorRippleLayer];
self.rippleDisplayLink = [CADisplayLink displayLinkWithTarget:self
selector:@selector(getCurrentRipple)];
[self.rippleDisplayLink addToRunLoop:[NSRunLoop mainRunLoop]
forMode:NSRunLoopCommonModes];
}
下面是繪制代碼:
主波
- (void)drawMainRipple{
self.mainRippleoffsetX += self.rippleSpeed;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 0, self.ripplePosition);
CGFloat y = 0.f;
for (float x = 0.f; x <= self.rippleWidth ; x++) {
y = self.rippleAmplitude * sin(1.2 * M_PI/ self.rippleWidth * x - self.mainRippleoffsetX *M_PI/180) + self.ripplePosition;
CGPathAddLineToPoint(path, nil, x, y);
}
CGPathAddLineToPoint(path, nil, self.rippleWidth, self.frame.size.height);
CGPathAddLineToPoint(path, nil, 0, self.frame.size.height);
CGPathCloseSubpath(path);
self.mainRippleLayer.path = path;
CGPathRelease(path);
}
次波
- (void)drawMinorRipple{
self.minorRippleoffsetX += self.rippleSpeed+0.1f;
CGMutablePathRef minorRipple = CGPathCreateMutable();
CGPathMoveToPoint(minorRipple, nil, 0, self.ripplePosition);
CGFloat y = 0.f;
for (float x = 0.f; x <= self.rippleWidth ; x++) {
y = self.rippleAmplitude * sin(1.2 * M_PI/ self.rippleWidth * x - self.minorRippleoffsetX*M_PI/360 ) + self.ripplePosition;
CGPathAddLineToPoint(minorRipple, nil, x, y);
}
CGPathAddLineToPoint(minorRipple, nil, self.rippleWidth, self.frame.size.height);
CGPathAddLineToPoint(minorRipple, nil, 0, self.frame.size.height);
CGPathCloseSubpath(minorRipple);
self.minorRippleLayer.path = minorRipple;
CGPathRelease(minorRipple);
}
實現效果
水波紋Gif
最后
本Demo的git庫地址:https://gitee.com/LiynXu/waterripple
歡迎訪問