Android 贝塞尔曲线

1:什么是贝塞尔曲线

       贝塞尔曲线(Bézier curve),是应用于二维图形应用程序的数学曲线。由支点和线段组成,主要结构包括起始点,结束点,控制点。控制点发生变化,贝塞尔曲线也跟着发生变化。贝塞尔曲线点的数量决定了曲线的阶数,一般N个点构成的N-1阶贝塞尔曲线,即3个点为二阶。

 2:一阶贝塞尔曲线  

      一阶贝塞尔曲线没有控制点,只有起始点和结束点,即一条直线连接p0和p1.

      

3:二阶贝塞尔曲线

      二阶贝塞尔曲线包含起始点(A) ,结束点(C)和控制点(B).

      

     具体在AB上有一点D,其中AD:AB=N;

      BC上一点E,其中BE:BC=N;

      DE中点F,  DF:DE=N;

      绘制所有满足条件的 点。连接而成的曲线就是二阶贝塞尔曲线。

    在android中绘制二阶贝塞尔曲线使用的是path.quadTo(float x1, float y1, float x2, float y2);

      参数x1代表控制点的x轴坐标,

     参数y1代表控制点的y轴坐标;

     参数x2代表结束点的x轴坐标,

    参数y2代表结束点的y轴坐标。

     简单绘制下二阶贝塞尔曲线如下:

核心绘制部分的代码如下:

 

 有兴趣的朋友可以看下完整代码:传送门

4:三阶贝塞尔曲线

  三阶贝塞尔曲线有两个控制点B和C.

   其中AE:AB=BF:BC=CG:CD=EH:EF=FI:FG=HJ:HI.

   最终三阶的贝塞尔曲线也就是由所有的J点连接而成。

   

    简单看下三阶的效果:

    

    代码传送门:三阶贝塞尔曲线代码

5:水波纹效果

      先上效果:

     

    绘制水波纹主要几个步骤

    1:首先绘制出类似于sin函数的曲线

     

    2:判断满屏一共多少个类似的曲线

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        setOnClickListener(this);
        //屏幕宽高
        screenWidth=w;
        screenHeight=h;

        startX=0;
        startY=h/2;

        //水波纹宽度
        waveLenth=200;
        //绘制的sin曲线个数
        waveCount = (int) Math.round(screenWidth / waveLenth + 1.5);
    }

    3:path连接所有的区域

    

   waveLenth:sin曲线宽度。
   waveCount:满屏状态sin曲线的个数
   


         mPath.reset();
        mPath.moveTo(-waveLenth+offset,startY);
        //绘制贝塞尔曲线
        for (int i=0;i<waveCount;i++){
            int totalOffset=waveLenth*i+offset;
            mPath.quadTo(totalOffset-waveLenth/4*3,startY-100,totalOffset-waveLenth/2,startY);
            mPath.quadTo(totalOffset-waveLenth/4,startY+100,totalOffset,startY);
        }

        mPath.lineTo(screenWidth,screenHeight);
        mPath.lineTo(0,screenHeight);
        mPath.close();
        canvas.drawPath(mPath,mPaint);

   

    4:设置offset,动画更新页面。

//设置waveview的点击动画,    
public void startAnimation() {
        valueAnimator= ValueAnimator.ofInt(0, waveLenth);
        valueAnimator.setDuration(1000);
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //水平方向的偏移量
                offset = ( int ) animation.getAnimatedValue();
                Log.e("xxx",offset+"");
                invalidate();
            }

        });
        valueAnimator.start();
    }

另外记得设置停止动画

 //停止动画
    public  void  onStop(){
       if (valueAnimator!=null){
           valueAnimator.end();
       }
    }

最后奉上github地址:BezierDemo   

    

   

   

猜你喜欢

转载自blog.csdn.net/qq_23025319/article/details/89642197