標籤:tar git raw 起點 cti name net new get
最近突然手癢就想搞個貝茲路徑做個水波紋效果玩玩,終於功夫不負有心人最後實現了想要的效果,一起來看下吧:
鎮樓
一:先一步一步來分解一下實現的過程
- 需要繪製一個正弦曲線(sin)或者餘弦曲線(cos)
- 通過水平平移曲線來的到像水波波動的效果
- 水平移動的同時還需要有水位上漲,也就是向上平移
- 裁剪畫布為圓形,在圓形地區繪製曲線
- 通過上面4步就可以實現了
二:現在就來實現第一步,繪製一個sin曲線;這裡畫了一張圖來協助理解,在PhotoShop中我們繪製一個貝茲路徑可以清楚的看到它的控制點
???繪製貝茲路徑我們必須要知道三個點:起點、控制點、終點;有了這三個點我們就可以繪製一段簡單二階貝茲路徑。我們可以看出 起點 控制點p1 x1 這三個點繪製了一段曲線,也就是通過path.quadTo()函數添加一個曲線路徑。
???假設我們需要繪製一個周期的sin曲線,那麼我們就只需要知道起點、一個周期的寬度、振幅;就可以繪製一個sin曲線了。
三:下面就來看下代碼的實際操作了,這裡就直接省略掉一些畫筆初始化的操作了可以點擊這裡查看源碼
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //擷取view的寬度 width = getViewSize(800, widthMeasureSpec); //擷取view的高度 height = getViewSize(400, heightMeasureSpec); //擷取起點座標 startPoint = new Point(0, height / 2);}
首先肯定是要擷取到畫布的大小才能確定好起點的座標,有了起點座標就可以開始繪製我們的曲線了
在ondraw()函數中進行曲線的繪製
/*sin曲線 1/4個周期的寬度*/private int cycle = 200;/*sin曲線振幅的高度*/private int waveHeight = 200;@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); path.moveTo(startPoint.x, startPoint.y); int j = 1; //迴圈繪製正弦曲線 迴圈一次半個周期 for (int i = 1; i <= 8; i++) { if (i % 2 == 0) { //波峰 path.quadTo(startPoint.x + (cycle * j), startPoint.y + waveHeight, startPoint.x + (cycle * 2) * i, startPoint.y); } else { //波穀 path.quadTo(startPoint.x + (cycle * j), startPoint.y - waveHeight, startPoint.x + (cycle * 2) * i, startPoint.y); } j += 2; } //繪製封閉的曲線 path.lineTo(width, height);//右下角 path.lineTo(startPoint.x, height);//左下角 path.lineTo(startPoint.x, startPoint.y);//起點 path.close(); canvas.drawPath(path, paint);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
經過上面一系例操作一個水波紋效果就出來啦
四:接下來就是水平移動這個曲線了為了移動起來更加好看,我們需要在螢幕外面開始繪製一個周期,如下:
//初始化的時候將起點移至螢幕外一個周期startPoint = new Point(-cycle * 4, height / 2);//繼續在ondraw()函數最後追加平移代碼//判斷是不是平移完了一個周期if (startPoint.x + 40 >= 0) { //滿了一個周期則恢複預設起點繼續平移 startPoint.x = -cycle * 4;}//每次波形的平移量 40startPoint.x += 40;postInvalidateDelayed(150);path.reset();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
只需要這樣就可以產生水波效果了,一起來看吧。
五:接下來就是要將畫布變成圓形了(其實還是個矩形,只是繪畫地區在你所裁剪的地區),然後在裡面實現水波紋就哦的K了;完整的繪製代碼如下:
@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); //裁剪畫布為圓形 Path circlePath = new Path(); circlePath.addCircle(width / 2, height / 2, width / 2, Path.Direction.CW); canvas.clipPath(circlePath); canvas.drawPaint(circlePaint); canvas.drawCircle(width / 2, height / 2, width / 2, circlePaint); //以下操作都是在這個圓形畫布中操作 //根據進度改變起點座標的y值 startPoint.y = (int) (height - (progress / 100.0 * height)); //起點 path.moveTo(startPoint.x, startPoint.y); int j = 1; //迴圈繪製正弦曲線 迴圈一次半個周期 for (int i = 1; i <= 8; i++) { if (i % 2 == 0) { path.quadTo(startPoint.x + (cycle * j), startPoint.y + waveHeight, startPoint.x + (cycle * 2) * i, startPoint.y); } else { path.quadTo(startPoint.x + (cycle * j), startPoint.y - waveHeight, startPoint.x + (cycle * 2) * i, startPoint.y); } j += 2; } //繪製封閉的曲線 path.lineTo(width, height);//右下角 path.lineTo(startPoint.x, height);//左下角 path.lineTo(startPoint.x, startPoint.y);//起點 path.close(); canvas.drawPath(path, paint); drawText(canvas, textPaint, progress + "%"); //判斷是不是平移完了一個周期 if (startPoint.x + 40 >= 0) { //滿了一個周期則恢複預設起點繼續平移 startPoint.x = -cycle * 4; } //每次波形的平移量 40 startPoint.x += 40; if (autoIncrement) { if (progress >= 100) { progress = 0; } else { progress++; } } postInvalidateDelayed(150); path.reset();}
Android自訂View——實現水波紋效果類似剩餘流量球