iOS 波浪曲線的繪製
iOS 波浪曲線的繪製
還是先上圖:
其實之前就一直想看一下 iOS 關於曲線繪製的相關類容,但由於剛剛步入職場,事情比較多。所以也沒什麼時間來看這些。剛好前段時間有空看了下,做了個 Demo,就上面那個左右搖擺的頭像。由於現在是在一家外包公司,也不追求什麼炫酷的特效,之前有個做 Android 的同事說研究這些純粹是浪費時間,但是我覺得吧,其實並不是這樣的,像我們 iOS 和 Android 做前端開發的, 80%的時間是在寫介面,還是很有必要了解一下這些影象究竟是如何展現在螢幕上的,我們又該如何去控制顯示的內容呢?
其實這方面的資料有很多,網上一搜一大把,主要還是要花時間去看。我們要分清楚 UIView 和 CALayer 之間的區別和聯絡,這裡我就不細說了,好了,步入正題:如何完成上圖所展示的效果呢?
讓我們來分解一下:要實現上圖的效果要實現哪些東西:
- 實現一個波浪曲線
- 加入一個頭像,並根據曲線的浮動調整頭像的位置
- 更具曲線的切線斜率調整頭像的左右偏移
只需要完成上面三個步驟,這個效果就實現了。首先,我們來看第一個:如何實現一個波浪曲線。
實現一個波浪曲線
像這樣的一條曲線,肯定是需要我們手動去繪製的,然後設定一個定時器,再去繪製它下一次出現的位置,但是我們該如何去繪製這樣的波浪曲線呢?
仔細看一下,這個曲線是不是很眼熟?是的,就是我們高中還是初中所學的正弦曲線,來想一下正弦曲線是怎麼畫的。

在想一下通式: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);
}
搞定!
相關文章
- canvas繪製sin正弦曲線Canvas
- Origin教程:DSC曲線的描述和繪製
- ROC曲線繪製與AUC計算
- 解析csv資料繪製曲線圖
- caffe的python介面繪製loss和accuracy曲線示例Python
- 函式的遞迴及科赫曲線繪製函式遞迴
- flutter 自定義view 繪製曲線統計圖FlutterView
- MPAndroidChart繪製曲線圖、柱狀圖總結Android
- 使用canvas繪製dribble風格水波浪Canvas
- WPF隨筆收錄-實時繪製心率曲線
- webGL入門-四階貝塞爾曲線繪製Web
- 基於 matplotlib 的抽象網格和能量曲線繪製程式抽象
- iOS使用Charts框架繪製折線圖iOS框架
- pyqt5+matplotlib繪製動態雙y軸曲線QT
- iOS股票K線圖、分時圖繪製iOS
- 自定義View合輯(6)-波浪(貝塞爾曲線)View
- ECharts,付費求教,有人能繪製出文中的 曲線圖表嘛!Echarts
- WPF開發隨筆收錄-心電圖曲線繪製
- 基於react的錄音及音訊曲線繪製的元件開發React音訊元件
- iOS UI繪製原理iOSUI
- iOS 繪製圓角iOS
- iOS開發_繪製圓角矩形虛線環iOS
- Flutter 自定義元件之貝塞爾曲線畫波浪球Flutter元件
- Android日常學習:OpenGL 實踐之貝塞爾曲線繪製Android
- R語言ggsurvplot繪製生存曲線報錯 : object of type ‘symbol‘ is not subsettableR語言ObjectSymbol
- Python的GDAL庫繪製多波段、長時序遙感影像時間曲線圖Python
- Flutter 實戰 - 用貝塞爾曲線畫一個帶文字的波浪球 WidgetFlutter
- canvas繪製直線Canvas
- SVG 繪製直線SVG
- canvas 繪製線條Canvas
- iOS 繪製漸變·基礎篇iOS
- 等值線圖的Python繪製方法Python
- SVG <polyline> 繪製折線SVG
- canvas 繪製雙線技巧Canvas
- PyQtGraph繪製折線圖QT
- AnyChart繪製折線圖
- Matplotlib 繪製折線圖
- MATLAB 繪製折線圖Matlab
- mapboxgl繪製3D線3D