Android-貝塞爾曲線實現水波紋動畫
Android 系統api提供了quadTo和rQuadTo實現二階貝塞爾曲線,三階貝塞爾曲線在這不做闡述,只不過是兩個控制點。

ed662587bd.jpg
原始碼地址: ofollow,noindex">https://github.com/StevenYan88/WaveView.git
效果圖

device-2018-10-19-155544.gif
首先看張二階貝賽爾的曲線

bzier.jpg
Path path = new Path(); //貝賽爾的起始點moveTo(x,y) path.moveTo(getWidth() / 2 - 200, getHeight() / 2); //quadTo 引數講解(x1,y1,x2,y2) //x1:控制點x座標 //y1:在控制點y座標 //x2:終點x座標 //y2:終點y座標 path.quadTo(getWidth() / 2 - 100, getHeight() / 2 - 100, getWidth() / 2, getHeight() / 2); path.quadTo(getWidth() / 2 + 100, getHeight() / 2 + 100, getWidth() / 2 + 200, getHeight() / 2); canvas.drawPath(path, mPaint);
quadTo和rQuadTo的區別
//rQuadTo引數講解(dx1,dy1,dx2,dy2): //dx1:控制點相對起點的x位移 //dy1:控制點相對起點的y位移 //dx2:終點相對起點的x位移 /dy2:終點相對起點的y位移 path.moveTo(getWidth() / 2 - 200, getHeight() / 2); path.rQuadTo(100, -100, 200, 0); path.rQuadTo(100, 100, 200, 0); canvas.drawPath(path, mPaint);
效果一樣,在這就不貼圖了。
quadTo引數講解(x1,y1,x2,y2):x1:控制點x座標,y1:在控制點y座標,x2:終點x座標,y2:終點y座標
rQuadTo引數講解(dx1,dy1,dx2,dy2):dx1:控制點相對起點的x位移,dy1:控制點相對起點的y位,dx2:終點相對起點的x位移,dy2:終點相對起點的y位移
實現水波紋動態的效果
實現水波紋動態效果無非是曲線向左一個偏移量dx,看過去想凹凸的曲線,於是形成了水波紋動態效果。看程式碼。
public class WaveView extends View { private Paint mPaint; private int mWidth; private int mHeight; private int mWaveHeight; private int mWaveDx; private int dx; public WaveView(Context context) { this(context, null); } public WaveView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setColor(Color.parseColor("#FF3891")); mPaint.setStyle(Paint.Style.FILL); //波長的長度(這裡設定為螢幕的寬度) mWaveDx = getResources().getDisplayMetrics().widthPixels; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //控制元件的寬高 mWidth = MeasureUtils.measureView(widthMeasureSpec, mWaveDx); mHeight = MeasureUtils.measureView(heightMeasureSpec, 300); //水波的高度 mWaveHeight = DensityUtil.dip2px(getContext(), 16); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawWave(canvas); } private void drawWave(Canvas canvas) { Path path = new Path(); path.reset(); path.moveTo(-mWaveDx + dx, mHeight / 2); for (int i = -mWaveDx; i < getWidth() + mWaveDx; i += mWaveDx) { path.rQuadTo(mWaveDx / 4, -mWaveHeight, mWaveDx / 2, 0); path.rQuadTo(mWaveDx / 4, mWaveHeight, mWaveDx / 2, 0); } //繪製封閉的區域 path.lineTo(mWidth, mHeight); path.lineTo(0, mHeight); //path.close() 繪製封閉的區域 path.close(); canvas.drawPath(path, mPaint); } public void startAnimation() { ValueAnimator valueAnimator = ValueAnimator.ofInt(0, mWaveDx); valueAnimator.setDuration(2000); valueAnimator.setRepeatCount(ValueAnimator.INFINITE); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //水平方向的偏移量 dx = ( int ) animation.getAnimatedValue(); invalidate(); } }); valueAnimator.start(); }
}
核心程式碼是drawWave()這個方法,startAnimation()是一個水平方向動畫,偏移量是dx,在Activity中呼叫。水波紋的高度(貝塞爾曲線的高度),顏色、大小都可以自定義。小編沒有寫,整個繪製水波紋動畫效果的思路和清晰。主要是搞懂quadTo和rQuadTo的區別和引數的意思。

qCode.jpg
Android開發之旅,和大家一起走!定期分享Androd技術乾貨,包括最新的android技術,ndk開發,資料結構和演算法。也會有些雜談......快快關注吧!