一继阻、國際慣例先上效果
二耻涛、實(shí)現(xiàn)思路
1、貝塞爾曲線實(shí)現(xiàn)
什么是貝塞爾曲線瘟檩,貝塞爾曲線的原理抹缕,二階、三階墨辛、四階卓研、五階等等更復(fù)雜的貝塞爾曲線感興趣的自己去了解,這里就不贅述了
Android中繪制貝塞爾曲線的Path類提供了四個(gè)方法
二階貝API:
public void quadTo(float x1, float y1, float x2, float y2)
public void rQuadTo(float dx1, float dy1, float dx2, float dy2)
三階API:
public void quadTo(float x1, float y1, float x2, float y2, float x3, float y3)
public void rQuadTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
推導(dǎo)過程(從其他網(wǎng)站趴的別人的),其中N階貝塞爾曲線可理解為有N條相連的線段奏赘,有N+1個(gè)頂點(diǎn):
(1)一階貝塞爾曲線:有頂點(diǎn)A寥闪、B,組成線段AB磨淌,利用線性插值原理疲憋,可得軌跡公式為:Path = (1-t)A + tB.
(2)二階貝塞爾曲線:有頂點(diǎn)A、B梁只、C缚柳,組成線段AB、BC搪锣,則有:
M = AB = (1-t)A + tB,
N = BC = (1-t)B + tC,
Path = (1-t)M + tN.
將M和N帶入Path秋忙,可得軌跡公式為:Path = (1-t)2A + 2t(1-t)B + t2C.
(3)三階貝塞爾曲線:有頂點(diǎn)A、B构舟、C灰追、D,組成線段AB旁壮、BC监嗜、CD,則有:
M = AB = (1-t)A + tB,
N = BC = (1-t)B + tC,
Q = CD = (1-t)C + tD,
S = MN = (1-t)M + tN,
T = NQ = (1-t)N + tQ,
Path = (1-t)S + tT,
將S和T帶入Path抡谐,再將M裁奇、N和Q帶入Path中的S和T,可得軌跡公式:Path = (1-t)3A + 3t(1-t)2B + 3t2(1-t)C + t3D.
部分代碼
2刽肠、正弦函數(shù)實(shí)現(xiàn)
一個(gè)很重要的網(wǎng)站:Des正xuanmos | 圖形計(jì)算器先利用這個(gè)網(wǎng)站套正弦曲線的表達(dá)式為y=Asin(ωx+φ)+k,把正玄圖畫出來
三條波浪正弦圖
部分代碼
//三條曲線相關(guān)的核心正弦曲線公式
private fun calcValue(mapX: Float, offset: Float, i: Int): Double {
var off = offset
off %= 2f
val sinFunc = sin(2 * (mapX + i) - off * Math.PI) + 1
val recessionFunc = perHeight / (4 + (mapX + i).toDouble().pow(2.0))
return -sinFunc * recessionFunc
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 從canvas層面去除繪制時(shí)鋸齒
canvas.setDrawFilter(mDrawFilter);
for (int i = 0; i < getWidth(); i++) {
// y = A * sin( wx + b) + h ; A: 浪高免胃; w:周期音五;b:初相;
float endY = (float) (20 * Math.sin(2 * Math.PI / getWidth() * i + mOffset1) + 300);
//畫第一條波浪
canvas.drawLine(i, 600, i, endY, mWavePaint);
//畫第二條波浪
float endY2 = (float) (20 * Math.sin(2 * Math.PI / getWidth() * i + mOffset2) + 300);
canvas.drawLine(i, 600, i, endY2, mWavePaint);
}
if (mOffset1 > Float.MAX_VALUE - 1) {//防止數(shù)值超過浮點(diǎn)型的最大值
mOffset1 = 0;
}
mOffset1 += mSpeed1;
if (mOffset2 > Float.MAX_VALUE - 1) {//防止數(shù)值超過浮點(diǎn)型的最大值
mOffset2 = 0;
}
mOffset2 += mSpeed2;
//刷新
postInvalidate();
}
總結(jié)
因公司項(xiàng)目保密性羔沙,大多數(shù)代碼暫時(shí)無法公開躺涝,只展示了一些思路和核心算法,望各位見諒扼雏,如果您開發(fā)過程中也用到類似的效果坚嗜,需要幫忙可臨時(shí)私信我,可適當(dāng)提供部分代碼