56.贝赛尔曲线初步(一)

来源:互联网 发布:华为网络机顶盒怎么样 编辑:程序博客网 时间:2024/06/07 11:53

转载请注明出处 http://blog.csdn.net/qq_31715429/article/details/54314178
本文出自:猴菇先生的博客

贝赛尔曲线有一阶、二阶、三阶、N阶
一阶就是一条直线,有起点终点,没有控制点,对应方法就是

canvas.drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint) ;

二阶为曲线,有起点终点,一个控制点,对应方法就是

path.quadTo(float x1, float y1, float x2, float y2);

其中x1、y1为控制点坐标, x2、y2为终点坐标,效果如下:

这里写图片描述

三阶由俩个控制点控制,对应方法就是

path.cubicTo(float x1, float y1, float x2, float y2, float x3, float y3);

其中x1、y1、x2、y2为两个控制点坐标, x3、y3为终点坐标,效果如下:

这里写图片描述

做一个demo巩固一下用法:

这里写图片描述

新建一个SecondBezierView继承View,重写构造方法、初始化画笔、固定起点和终点的坐标,重写onTouchEvent()方法获取当前点击的点为控制点:

    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_MOVE:                mControlX = event.getX();                mControlY = event.getY();                invalidate();                break;        }        return true;    }

在onDraw()方法中画点、画连接线、画文本、画二阶贝塞尔曲线

    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.drawCircle(mStartX, mStartY, 8, mLinePaint);        canvas.drawText("起点", mStartX, mStartY, mLinePaint);        canvas.drawCircle(mEndX, mEndY, 8, mLinePaint);        canvas.drawText("终点", mEndX, mEndY, mLinePaint);        canvas.drawCircle(mControlX, mControlY, 8, mLinePaint);        canvas.drawText("控制点", mControlX, mControlY, mLinePaint);        canvas.drawLine(mStartX, mStartY, mControlX, mControlY, mLinePaint);        canvas.drawLine(mEndX, mEndY, mControlX, mControlY, mLinePaint);        mBezierPath.reset();//因为不断重绘,path的路径也要重置,不然页面上会显示很多条线        mBezierPath.moveTo(mStartX, mStartY);//移至起点        mBezierPath.quadTo(mControlX, mControlY, mEndX, mEndY);//二阶贝塞尔曲线,传入控制点和终点坐标        canvas.drawPath(mBezierPath, mBezierPaint);    }

最后添加一个回弹的动画,用的是OvershootInterpolator插值器,在onTouchEvent的MotionEvent.ACTION_UP中:

    case MotionEvent.ACTION_UP:        ValueAnimator animX = ValueAnimator.ofFloat(mControlX, getWidth() / 2);        animX.setDuration(500);        animX.setInterpolator(new OvershootInterpolator());        animX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                mControlX = (float) animation.getAnimatedValue();                invalidate();            }        });        animX.start();        ValueAnimator animY = ValueAnimator.ofFloat(mControlY, getHeight() / 2);        animY.setDuration(500);        animY.setInterpolator(new OvershootInterpolator());        animY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                mControlY = (float) animation.getAnimatedValue();                invalidate();            }        });        animY.start();        break;

再来个三阶的

这里写图片描述

主要就是用到了多点触控:

    private boolean mIsSecondPoint = false;    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction() & MotionEvent.ACTION_MASK) {//多点触控            case MotionEvent.ACTION_POINTER_DOWN:                mIsSecondPoint = true;                break;            case MotionEvent.ACTION_POINTER_UP:                mIsSecondPoint = false;                break;            case MotionEvent.ACTION_MOVE:                mControlX1 = event.getX(0);//获取控制点1的横纵坐标                mControlY1 = event.getY(0);                if (mIsSecondPoint) {                    mControlX2 = event.getX(1);//获取控制点2的横纵坐标                    mControlY2 = event.getY(1);                }                invalidate();                break;        }        return true;    }

然后再onDraw()中画三阶贝赛尔曲线

    mBezierPath.reset();    mBezierPath.moveTo(mStartX, mStartY);    mBezierPath.cubicTo(mControlX1, mControlY1, mControlX2, mControlY2, mEndX, mEndY);    canvas.drawPath(mBezierPath, mBezierPaint);

大功告成,打完收工

8 0
原创粉丝点击