贝塞尔曲线(一) 认识

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/darling_R/article/details/68969530

转载请注明出处:http://blog.csdn.net/darling_R/article/details/68969530

看了徐医宜生 的视频,现在练习了一下贝塞尔曲线,其实挺简单的。下面来看看代码吧
首先借用官方的一个图来演示一下什么是贝塞尔曲线
也可以去[这里]看详细介绍
(https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Linear_curves)
二阶贝塞尔曲线
这里写图片描述
三阶贝塞尔曲线
这里写图片描述
二阶效果图:
这里写图片描述
主要弄清楚 起点 、终点、控制点,然后使用Android提供的贝塞尔曲线api就行了,
二阶的:在onDraw 方法中调用
mPath.quadTo(mFlagPointX, mFlagPointY, mEndPointX, mEndPointY);
前两个参数就是 控制点的坐标,后两个则是终点坐标,起点坐标在初始化path时就确定了,因为绘制曲线,要调用drawpath方法,所以在此之前要定义一个Path,并且在绘制之前,调用reset方法重置,并且,将path移动到起点 mPath.moveTo(mStartPointX,mStartPointY);
重写 OnTouch方法,

case MotionEvent.ACTION_MOVE:
     mFlagPointX = event.getX();
     mFlagPointY = event.getY();
     invalidate();
     break;

在手指移动的过程中,记录控制点的坐标,可以让控制点随着手指的移动而移动
在抬起的事件中添加一个动画效果:

case MotionEvent.ACTION_UP:

                float mTempX = mStartPointX + (mEndPointX - mStartPointX) / 2;
                float mTempY = mStartPointY + (mEndPointY - mStartPointY) / 2;

                ValueAnimator valueAnimatorX = ValueAnimator.ofFloat(mFlagPointX,mTempX);
                valueAnimatorX.setDuration(500);
                valueAnimatorX.setInterpolator(new OvershootInterpolator());
                valueAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        mFlagPointX = (float) animation.getAnimatedValue();
                        invalidate();
                    }
                });
                valueAnimatorX.start();

                ValueAnimator valueAnimatorY = ValueAnimator.ofFloat(mFlagPointY,mTempY);
                valueAnimatorY.setDuration(500);
                valueAnimatorY.setInterpolator(new OvershootInterpolator());
                valueAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        mFlagPointY = (float) animation.getAnimatedValue();
                        invalidate();
                    }
                });
                valueAnimatorY.start();

                break;

三阶效果图:
这里写图片描述
三阶贝塞尔曲线跟二阶差不多,唯一多出来的知识点就是涉及到多点触控,在OnTouch事件里面,

case MotionEvent.ACTION_POINTER_DOWN:
//监听第二根手指按下
                isSecond = true;
                break;
            //多点触控 抬起
            case MotionEvent.ACTION_POINTER_UP:
                isSecond = false;
                break;
mPath.cubicTo(mFlagPointOneX, mFlagPointOneY,mFlagPointTwoX,mFlagPointTwoY, mEndPointX, mEndPointY);

api也有点不同,就是多了控制点的坐标,
二阶跟三阶都有两个方法:rQuadTo(),rCubicTo(),这两个里面的参数都是相对坐标,而quadTo()和cubicTo()参数坐标都是绝对坐标,这里需要注意一下;
这里附上三阶的源码,对应的可以看出来二阶的:

public class ThirdBezierView extends View {

    //起点坐标
    private float mStartPointX;
    private float mStartPointY;
    //终点坐标
    private float mEndPointY;
    private float mEndPointX;
    //控制点坐标
    private float mFlagPointOneX;
    private float mFlagPointOneY;
    private float mFlagPointTwoX;
    private float mFlagPointTwoY;
    //曲线画笔
    private Paint mBezierPaint;
    //连线画笔
    private Paint mLinePaint;
    //文字画笔
    private Paint mTextPait;
    //
    private Path mPath;

    private boolean isSecond = false;//标志第二个手指是否按下


    public ThirdBezierView(Context context) {
        super(context);
    }

    public ThirdBezierView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        mPath = new Path();

        mBezierPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBezierPaint.setColor(0xfff3a344);
        mBezierPaint.setStrokeWidth(8);
        mBezierPaint.setStyle(Paint.Style.STROKE);

        mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLinePaint.setStyle(Paint.Style.STROKE);

        mTextPait = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPait.setStyle(Paint.Style.STROKE);
        mTextPait.setTextSize(26);
    }

    public ThirdBezierView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //初始化坐标点
        mStartPointX = w / 4;
        mStartPointY = h / 3;

        mEndPointX = 3 * w / 4;
        mEndPointY = h / 3;

        mFlagPointOneX = w / 2 - 200;
        mFlagPointOneY = h / 4;
        mFlagPointTwoX = w / 2 + 200;
        mFlagPointTwoY = h / 4;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPath.reset();
        mPath.moveTo(mStartPointX, mStartPointY);
        //链接起点与控制点
        canvas.drawLine(mStartPointX, mStartPointY, mFlagPointOneX, mFlagPointOneY, mLinePaint);
        canvas.drawLine(mFlagPointOneX, mFlagPointOneY, mFlagPointTwoX, mFlagPointTwoY, mLinePaint);
        canvas.drawLine(mFlagPointTwoX, mFlagPointTwoY, mEndPointX, mEndPointY, mLinePaint);

        canvas.drawText("起点",mStartPointX,mStartPointY,mTextPait);
        canvas.drawText("控制点",mFlagPointOneX,mFlagPointOneY,mTextPait);
        canvas.drawText("控制点",mFlagPointTwoX,mFlagPointTwoY,mTextPait);
        canvas.drawText("终点",mEndPointX,mEndPointY,mTextPait);


        mPath.cubicTo(mFlagPointOneX, mFlagPointOneY,mFlagPointTwoX,mFlagPointTwoY, mEndPointX, mEndPointY);

        canvas.drawPath(mPath, mBezierPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction() &MotionEvent.ACTION_MASK) {
            //多点触控标志按下
            case MotionEvent.ACTION_POINTER_DOWN:
                isSecond = true;
                break;
            //多点触控 抬起
            case MotionEvent.ACTION_POINTER_UP:
                isSecond = false;
                break;
            case MotionEvent.ACTION_MOVE:
                mFlagPointOneX = event.getX(0);
                mFlagPointOneY = event.getY(0);
                if(isSecond){
                    mFlagPointTwoX = event.getX(1);
                    mFlagPointTwoY = event.getY(1);
                }
                invalidate();
                break;

        }
        return true;

    }
}

猜你喜欢

转载自blog.csdn.net/darling_R/article/details/68969530
今日推荐