Android贝塞尔曲线-水波篇

在做自定义view时,很多时候会用到贝塞尔曲线这个东西去实现一些效果,像以前写的那个仿直播点赞动画的实现就是用到了贝塞尔曲线,这次说的水波也会用到贝塞尔曲线这个东西。

Android贝塞尔曲线api

首先看下贝塞尔曲线公式:

一阶

这里写图片描述

二阶

这里写图片描述

其中p0是起点,p1是控制点,p2是终点

三阶

这里写图片描述

其中p0是起点,p1,p2是控制点,p3是终点

Android做好了相应的api,分别如下:

二阶:

quadTo(float x1, float y1, float x2, float y2)
rQuadTo(float dx1, float dy1, float dx2, float dy2)

三阶:

cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
rCubicTo(float x1, float y1, float x2, float y2,float x3, float y3)

因为这里主要用到了二阶杯赛曲线,所以主要讲一下这个

api解释及运用

quadTo(float x1, float y1, float x2, float y2)

quadTo是参数解释:
x1:控制点x坐标
y1:在控制点y坐标
x2:终点x坐标
y2:终点y坐标

先看段例子:

 pathRed.moveTo(getWidth()/2-100,getHeight()/2);
 pathRed.quadTo(getWidth()/2-50,getHeight()/2-50,getWidth()/2,getHeight()/2);
 pathRed.quadTo(getWidth()/2+50,getHeight()/2+50,getWidth()/2+100,getHeight()/2);
 canvas.drawPath(pathRed,paintRed);

得到的图形如下

Android贝塞尔曲线-水波篇_第1张图片

这里解释一点:当连续调用quadTo的时候上一个quadTo的终点即为写下一个quadTo的起点

rQuadTo(float dx1, float dy1, float dx2, float dy2)

dx1:控制点相对起点的x位移
dy1:控制点相对起点的y位移
dx2:终点相对起点的x位移
dy2:终点相对起点的y位移

把上面那段代码改改即为如下所示:

 pathRed.moveTo(getWidth()/2-100,getHeight()/2);
 pathRed.rQuadTo(50,-50,100,0);
 pathRed.rQuadTo(50,50,100,0);

图就不上了,也是同样的效果

水波实现

首先先做出来一个静态的水波,如下图所示:

Android贝塞尔曲线-水波篇_第2张图片

再看下代码

 public void drawMyPath(int wavehigh,Path path){
        path.reset();
        path.moveTo(-waveRed,high/2);
        for (int i = -waveRed; i < getWidth()+waveRed; i+=waveRed) {
            path.rQuadTo(waveRed/4,-wavehigh,waveRed/2,0);
            path.rQuadTo(waveRed/4,wavehigh,waveRed/2,0);

        }
        path.lineTo(getWidth(),getHeight());
        path.lineTo(0,getHeight());
        path.close();
    }

wavehigh是定义的水波高度,waveRed是指水波长度,我们要做的就是在屏幕左右各预留一个波长以便后续的移动。

接下来要做的就是怎么能让波形移动了,因为已经预留了两边的波长所以只要让path的起点慢慢移动一个波长就形成了视觉上的水波效果

代码如下:

 public void drawMyPath(int wavehigh,Path path,int y){
        path.reset();
        path.moveTo(-waveRed+y+dx,high/2);
        for (int i = -waveRed; i < getWidth()+waveRed; i+=waveRed) {
            path.rQuadTo(waveRed/4,-wavehigh,waveRed/2,0);
            path.rQuadTo(waveRed/4,wavehigh,waveRed/2,0);

        }
        path.lineTo(getWidth(),getHeight());
        path.lineTo(0,getHeight());
        path.close();
    }
 public void startAnimation(){
        ValueAnimator animator=ValueAnimator.ofInt(0,waveRed);
        animator.setDuration(2000);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setInterpolator(new LinearInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                dx= (int) valueAnimator.getAnimatedValue();
                if (dx == waveRed) {
                    dx=0;

                }

                postInvalidate();
            }
        });
        animator.start();



    }

然后在外部调用一下让动画开始执行就行,看下具体效果:

Android贝塞尔曲线-水波篇_第3张图片

那这时我想做多条水波怎么办呢,还记得前面drawMyPath方法里的y参数吗,它就是控制起点位置,然后再改变一下水波高度就行了

Android贝塞尔曲线-水波篇_第4张图片

我是随便设置的,可能不太明显,能看出来就行

好了差不多说完了,下一篇说下怎么做出圆形水波view

你可能感兴趣的:(android)