Android-貝塞爾曲線實現水波紋動畫

local0發表於2021-09-09

Android 系統api提供了quadTo和rQuadTo實現二階貝塞爾曲線,三階貝塞爾曲線在這不做闡述,只不過是兩個控制點。
原始碼地址:

效果圖
圖片描述

首先看張二階貝賽爾的曲線
圖片描述

     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的區別和引數的意思。有問題可以留言!

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/132/viewspace-2815567/,如需轉載,請註明出處,否則將追究法律責任。

相關文章