iOS:一个简单的波浪形动画的实现

代码:demo
效果图:
wave.gif
分析:
通过动画的展示我们可以看到,这种类似于波浪的动画可以抽象成 三角函数
sin函数
只要函数的X坐标不断地偏移,在固定的显示的区域内,就会出现我们想要的波浪效果;
实现方式:

  • 自定义一个继承自UIView的类WaterWaveView
  • 重写初始化方法:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    -(id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
    self.backgroundColor = [UIColor clearColor];
    offSetOfSin = 0; //X轴坐标偏移量
    coordinateY = 50; //Y轴坐标的基准点(波浪的中间线)
    waterColor = [UIColor blueColor];//波浪的填充色
    [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(animateion) userInfo:nil repeats:YES];//通过定时器,不断偏移x轴坐标,重绘图像,实现效果
    }
    return self;
    }
  • animation 代码解释:
1
2
3
4
-(void)animation{
offSetOfSin += 0.1;
[self setNeedsDisplay];
}

关于为什么要执行

1
offSetOfSin += 0.1;

笔者在下面会解释,我们先来看,为什么要调用

1
[self setNeedsDisplay];

UIView的setNeedsDisplay会自动调用drawRect:方法,这样就可以拿到UIGraphicsGetCurrentContext,就可以进行绘画了。

  • 重写-(void)drawRect:(CGRect)rect方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-(void)drawRect:(CGRect)rect{
CGContextRef context = UIGraphicsGetCurrentContext();//获取上下文,所谓的上下文,读者可以理解成一个用来画画的画板。
CGMutablePathRef path = CGPathCreateMutable();//创建一条绘图的路径
CGContextSetLineWidth(context, 1);//设置线的宽度
CGContextSetFillColorWithColor(context, [waterColor CGColor]);//设置填充色
CGPathMoveToPoint(path, nil, 0, coordinateY);//设置起点
//添加一大堆绘制的点(绘制波浪线需要的点)
for (float x = 0; x<=100; x++) {
float y = sin(x /180*M_PI + 4*offSetOfSin/M_PI) * 5 + coordinateY;
CGPathAddLineToPoint(path, nil, x, y);
}
CGPathAddLineToPoint(path, nil, rect.size.width, rect.size.height); //这个点,确定了绘制的方向,即向下绘制
CGPathAddLineToPoint(path, nil, 0, rect.size.height);//这个点确保下方类似于一个矩形
// 注意:绘制的时候按照点的先后顺序绘制线
CGContextAddPath(context, path);//把绘制直线的绘图信息保存到图形上下文中
CGContextFillPath(context);//填充绘制区域
CGContextDrawPath(context, kCGPathStroke);//填充规则
CGPathRelease(path);//但凡通过quarzt2d中带有creat/copy/retain方法创建出来的值都必须手动的释放
}

注意下面这段代码:

1
2
3
4
for (float x = 0; x<=100; x++) {
float y = sin(x /180*M_PI + 4*offSetOfSin/M_PI) * 5 + coordinateY;
CGPathAddLineToPoint(path, nil, x, y);
}

  • x是float类型,而不是int类型,如果换成int类型,得到的是一些离散的点,得到的动画也会发生改变

wave.gif

由于绘制路径全部是直线,上面的那段代码绘制出来的图像并不是圆形,而是:
wave03

读者看到的圆形,是因为遮罩的存在

1
2
3
4
5
6
7
UIView * view = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
view.backgroundColor = [UIColor redColor];
view.layer.cornerRadius = 50;
view.layer.masksToBounds = YES;
WaterWaveView * waterView = [[WaterWaveView alloc]initWithFrame:view.bounds];
[view addSubview:waterView];
[self.view addSubview:view];

参考:
http://www.cnblogs.com/wendingding/p/3782679.html
http://blog.sina.com.cn/s/blog_6853c0db0101imt7.html
http://www.tuicool.com/articles/FfEBRf7