最新消息:文章中包含代码时,请遵守代码高亮规范!

Android Bezier曲线之三阶Bezier曲线【原创】

Android 李, 泰愚 176浏览 0评论

上次记录了一篇Bezier曲线基本的二阶Bezier曲线的学习,今天来说说Bezier曲线中的三阶曲线。

关于Bezier 曲线,例如使得曲线更加圆滑,用于动画的绘制等等应用场景也就不在赘述,现在直接上代码来看。

绘制一条三阶Bezier曲线需要四个点,起点,终点和两个控制点:

private float mStartPointX;
private float mStartPointY;

private float mEndPointX;
private float mEndPointY;

private float mFlagPointOneX;
private float mFlagPointOneY;
private float mFlagPointTwoX;
private float mFlagPointTwoY;

private Paint mPaintBezier;
private Paint mPaintFlag;
private Paint mPaintFlagText;

private Path mPath;
private boolean isSecondPoint = false;

除了这四个点外,再定义了三个绘制点以及线的画笔。另外mPath变量为曲线的路径,boolean型变量isSecondPoint用于再点击时间中做判断用,后面会看到。

用到的构造方法,用于变量的初始化:

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

    mPaintBezier = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintBezier.setStrokeWidth(8);
    mPaintBezier.setStyle(Paint.Style.STROKE);

    mPaintFlag = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintFlag.setStrokeWidth(3);
    mPaintFlag.setStyle(Paint.Style.STROKE);

    mPaintFlagText = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintFlagText.setStyle(Paint.Style.STROKE);
    mPaintFlagText.setTextSize(20);
}

接着是onSizeChanged方法,也是对一些变量的赋值操作,确定起始点和终点,控制点的第一次位置,mPath的初始化:

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mStartPointX = w/4;
    mStartPointY = h/2 - 200;

    mEndPointX = w*3/4;
    mEndPointY = h/2 - 200;

    mFlagPointOneX = w/2 - 100;
    mFlagPointOneY = h/2 - 300;
    mFlagPointTwoX = w/2 + 100;
    mFlagPointTwoY = h/2 - 300;

    mPath = new Path();
}

onDraw方法中,先将path的起点移动到起始点,不同于二阶Bezier的是这次调用cubicTo方法绘制三阶r曲线。且绘制几个辅助点旁的介绍文字,且起始点,终点分别和控制点用直线连接,看起来更加直观:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    mPath.reset();
    mPath.moveTo(mStartPointX, mStartPointY);
    mPath.cubicTo(mFlagPointOneX, mFlagPointOneY, mFlagPointTwoX, mFlagPointTwoY, mEndPointX, mEndPointY);

    canvas.drawPoint(mStartPointX, mStartPointY, mPaintFlag);
    canvas.drawText("起点", mStartPointX, mStartPointY, mPaintFlagText);
    canvas.drawPoint(mEndPointX, mEndPointY, mPaintFlag);
    canvas.drawText("终点", mEndPointX, mEndPointY, mPaintFlagText);
    canvas.drawPoint(mFlagPointOneX, mFlagPointOneY, mPaintFlag);
    canvas.drawText("控制点1", mFlagPointOneX, mFlagPointOneY, mPaintFlagText);
    canvas.drawText("控制点2", mFlagPointTwoX, mFlagPointTwoY, mPaintFlagText);

    canvas.drawLine(mStartPointX, mStartPointY, mFlagPointOneX, mFlagPointOneY, mPaintFlag);
    canvas.drawLine(mFlagPointOneX, mFlagPointOneY, mFlagPointTwoX, mFlagPointTwoY, mPaintFlag);
    canvas.drawLine(mEndPointX, mEndPointY, mFlagPointTwoX, mFlagPointTwoY, mPaintFlag);

    canvas.drawPath(mPath, mPaintBezier);
}

最后重写onTouchEvent方法,用于当你将程序跑起来时,可以通过触摸滑动两个控制点,从而看到不同控制点下的三阶Bezier曲线,使得看起来更加直观,这里就是用到isSecondPoint的地方,用来是两个控制点都可以滑动变换位置,且调用invalidate方法进行重绘:

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_POINTER_DOWN:
            isSecondPoint = true;
            break;
        case MotionEvent.ACTION_POINTER_UP:
            isSecondPoint = false;
            break;
        case MotionEvent.ACTION_MOVE:
            mFlagPointOneX = event.getX(0);
            mFlagPointOneY = event.getY(0);
            if(isSecondPoint) {
                mFlagPointTwoX = event.getX(1);
                mFlagPointTwoY = event.getY(1);
            }
            invalidate();
            break;
    }
    return true;
}

最后当自定义的这个控件写好后,将其放入布局中,预览图,也就是跑到手机上的界面如下:

当程序运行时,手指触摸屏幕滑动,两个控制点会随之变化,即可看到不同控制点下的三阶Bezier曲线了。

转载时请注明出处及相应链接,本文永久地址:http://blog.it985.com/22187.html


pay_weixin
pay_weixin
微信打赏
pay_weixin
支付宝打赏
感谢您对作者rick的打赏,我们会更加努力!    如果您想成为作者,请点我

您必须 登录 才能发表评论!