iOS 波浪曲线的绘制
还是先上图:

在想一下通式:y=Asin(wx+u)+K 对就是这么简单,那参数代表的又是什么呢?
- A :振幅
- w :角速度 w = 2PI/T T:周期
- u :初相
- K :y 轴偏移
有了这个公式,我们又该如何在屏幕上绘制正弦曲线呢?
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 0, 0);
CGFloat y = 0.0f;
for (float x = 0.f; x <= self.width; x++) {
y = self.A1 * sin(self.w*x + self.u1) + self.K1;
CGPathAddLineToPoint(path, nil, x, y);
x++;
}
CGPathAddLineToPoint(path, nil, self.width, self.height);
CGPathAddLineToPoint(path, nil, 0, self.height);
CGPathCloseSubpath(path);
self.waveLayer1.path = path;
CGPathRelease(path);
Build 运行一下,是不是就有了一个正弦曲线呢?接下来就要让正弦曲线动起来,这就要设置定时器去重绘这条曲线了。
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(wave)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
- (void)wave {
offset += self.offsetX;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 0, (self.A1*sin(offset + self.u1) + self.K1));
CGFloat y = 0.0f;
for (float x = 0.f; x <= self.width; x++) {
y = self.A1 * sin(self.w*x + offset + self.u1) + self.K1;
CGPathAddLineToPoint(path, nil, x, y);
x++;
}
CGPathAddLineToPoint(path, nil, self.width, self.height);
CGPathAddLineToPoint(path, nil, 0, self.height);
CGPathCloseSubpath(path);
self.waveLayer1.path = path;
CGPathRelease(path);
}
offset : 波浪曲线的初始偏移量
offsetX : 波浪曲线每次刷新偏移量
再附一个参数初始化:
- (void)initData {
self.A1 = 8;
self.K1 = 80;
self.u1 = M_PI*3/8.0f;
self.offsetX = 0.03;
offset = 0;
self.w = M_PI/180;
}
这样波浪曲线就完成了。
添加头像
初始化一个 UIImageView 放在屏幕中间,每次刷新波浪曲线的时候,都去改变头像位置
- (void)wave {
offset += self.offsetX;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 0, (self.A1*sin(offset + self.u1) + self.K1));
CGFloat y = 0.0f;
for (float x = 0.f; x <= self.width; x++) {
y = self.A1 * sin(self.w*x + offset + self.u1) + self.K1;
CGPathAddLineToPoint(path, nil, x, y);
x++;
}
if (self.floatImageView != nil) {
y = self.A1 * sin(self.w*(self.width/2.0 ) + offset + self.u1) + self.K1;
self.floatImageView.centerY = y - 30;
}
CGPathAddLineToPoint(path, nil, self.width, self.height);
CGPathAddLineToPoint(path, nil, 0, self.height);
CGPathCloseSubpath(path);
self.waveLayer1.path = path;
CGPathRelease(path);
}
头像偏移
关于头像的偏移,这里需要算出头像偏移角度,也就是与 X 轴的夹角。我们需要先算出正弦曲线在中间点的斜率。关于切线斜率怎么求呢? 高数老师告诉你:对函数求导后 x 处的值为斜率。那么对 y=Asin(wx+u)+K 求导:
y`= Awcos(wx + u)
获得屏幕中心的斜率为 k, 根据公式 k = tana
角度:a = arctank
这个角度便是我们需要的头像的偏移角度了,加在循环里面,每次再改变头像的角度。
- (void)wave {
offset += self.offsetX;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 0, (self.A1*sin(offset + self.u1) + self.K1));
CGFloat y = 0.0f;
for (float x = 0.f; x <= self.width; x++) {
y = self.A1 * sin(self.w*x + offset + self.u1) + self.K1;
CGPathAddLineToPoint(path, nil, x, y);
x++;
}
if (self.floatImageView != nil) {
y = self.A1 * sin(self.w*(self.width/2.0 ) + offset + self.u1) + self.K1;
self.floatImageView.centerY = y - 30;
CGFloat angel = atan(self.A1*(M_PI/60)*cos(self.w*(ScreenWidth/2.0f) + offset + self.u1));
self.floatImageView.transform = CGAffineTransformMakeRotation(angel / M_PI);
}
CGPathAddLineToPoint(path, nil, self.width, self.height);
CGPathAddLineToPoint(path, nil, 0, self.height);
CGPathCloseSubpath(path);
self.waveLayer1.path = path;
CGPathRelease(path);
}
搞定!
网友评论