Android贝塞尔曲线——曲线进阶

作者: 邢皓翔 | 来源:发表于2017-01-22 21:05 被阅读442次

    本文在我的CSDN同步发布,Android贝塞尔曲线——曲线进阶

    Hello,大家好,今天我的题目是Android贝塞尔曲线——曲线进阶,那么为什么叫做进阶呢?那当然是之前我写过初级的内容咯,没有读过的小伙伴可以点击Android贝塞尔曲线——曲线初体验来进行查看。

    今天来进阶一下曲线,上次我为大家带来的是贝塞尔曲线的初级实现,也就是二阶贝塞尔曲线,今天我想为大家说一下三阶贝塞尔曲线,其实也是非常简单的。我的目标是为大家带来最干的货。辣么,我们开始吧!

    什么是贝塞尔三阶?##

    那么有人要问了,什么是贝塞尔三阶曲线呢,他与二阶曲线有什么不同?我也不知道这个有人是哪位,不过他问的问题总是这么的犀利。。那么我来回答一下。众所周知,贝塞尔曲线二阶是由一个起点、一个控制点、一个终点来构成,那么三阶自然就是多出了一个控制点。 文字总是这么苍白无力,还是来看图吧!

    三阶贝塞尔曲线

    上图就是三阶贝塞尔曲线的基本形态,是不是比二阶多出了一个控制点。那么我们继续来看一下它的动态绘制过程吧!

    动态贝塞尔三阶曲线

    可见,三阶贝塞尔曲线从P0点经过P1、P2两个控制点最后到P3的终点完成了这条曲线的绘制。

    撸码时间##

    那么我们开始正式的撸码,首先创建一个BezierThiredView 让他继承View,如我下面的代码。

    public class BezierThiredView extends View {
    
        // 开始坐标
        private float startXPoint;
        private float startYPoint;
    
        // 结束坐标
        private float endXPoint;
        private float endYPoint;
    
        // 两个控制点
        private float conOneXPoint;
        private float conOneYPoint;
        private float conTwoXPoint;
        private float conTwoYPoint;
    
    
        // 画笔、路径
        private Path mPath;
        private Paint mPaint;
        private Paint mPaintCon;
        private Paint mPaintText;
    
        public BezierThiredView(Context context) {
            super(context);
        }
    
        public BezierThiredView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(Color.RED);
            mPaint.setStrokeWidth(8);
    
            mPaintCon = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaintCon.setStyle(Paint.Style.STROKE);
            mPaintCon.setStrokeWidth(3);
    
            mPaintText = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaintText.setStyle(Paint.Style.STROKE);
            mPaintText.setTextSize(20);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            startXPoint = w / 4;
            startYPoint = h / 2;
    
            endXPoint = w * 3 / 4;
            endYPoint = h / 2;
    
            conOneXPoint = w / 2 - 100;
            conOneYPoint = h / 2 - 400;
    
            conTwoXPoint = w / 2 + 100;
            conTwoYPoint = h / 2 - 400;
            mPath = new Path();
        }
    
        public BezierThiredView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mPath.reset();
            mPath.moveTo(startXPoint,startYPoint);
            mPath.cubicTo(conOneXPoint,conOneYPoint,conTwoXPoint,conTwoYPoint,endXPoint,endYPoint);
            canvas.drawPoint(startXPoint,startYPoint,mPaintCon);
            canvas.drawText("P0",startXPoint-50,startYPoint,mPaintText);
            canvas.drawPoint(endXPoint,endYPoint,mPaintCon);
            canvas.drawText("P3",endXPoint+50,endYPoint,mPaintText);
            canvas.drawPoint(conOneXPoint, conOneYPoint,mPaintCon);
            canvas.drawText("P1", conOneXPoint-50, conOneYPoint,mPaintText);
            canvas.drawPoint(conTwoXPoint, conTwoYPoint,mPaintCon);
            canvas.drawText("P2", conTwoXPoint+50, conTwoYPoint,mPaintText);
    
            canvas.drawLine(startXPoint,startYPoint, conOneXPoint, conOneYPoint,mPaintCon);
            canvas.drawLine(conOneXPoint, conOneYPoint,conTwoXPoint,conTwoYPoint,mPaintCon);
            canvas.drawLine(conTwoXPoint, conTwoYPoint,endXPoint,endYPoint,mPaintCon);
            canvas.drawPath(mPath,mPaint);
        }
    }
    
    

    跟着我上面代码就可以画出一条三阶贝塞尔曲线,其中path.cubicTo是系统提供给我们绘制三阶曲线的专用方法,我们来把他放到布局中来运行一下看看效果,这里我就省略添加自定义view到布局这段代码了。

    三阶贝塞尔曲线效果图

    这个样子我能做出来你们也一定可以哦,Duang!


    duang

    为了节省篇幅我也把辅助线一并画出来,下面我要带大家实现一下拖拽效果。

    废话不说了,直接上代码!

    public class BezierThiredView extends View {
    
        // 开始坐标
        private float startXPoint;
        private float startYPoint;
    
        // 结束坐标
        private float endXPoint;
        private float endYPoint;
    
        // 两个控制点
        private float conOneXPoint;
        private float conOneYPoint;
        private float conTwoXPoint;
        private float conTwoYPoint;
    
    
        // 画笔、路径
        private Path mPath;
        private Paint mPaint;
        private Paint mPaintCon;
        private Paint mPaintText;
    
        private boolean isPointDown; // 手指是否按下
    
        public BezierThiredView(Context context) {
            super(context);
        }
    
        public BezierThiredView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(Color.RED);
            mPaint.setStrokeWidth(8);
    
            mPaintCon = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaintCon.setStyle(Paint.Style.STROKE);
            mPaintCon.setStrokeWidth(3);
    
            mPaintText = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaintText.setStyle(Paint.Style.STROKE);
            mPaintText.setTextSize(20);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            startXPoint = w / 4;
            startYPoint = h / 2;
    
            endXPoint = w * 3 / 4;
            endYPoint = h / 2;
    
            conOneXPoint = w / 2 - 100;
            conOneYPoint = h / 2 - 400;
    
            conTwoXPoint = w / 2 + 100;
            conTwoYPoint = h / 2 - 400;
            mPath = new Path();
        }
    
        public BezierThiredView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mPath.reset();
            mPath.moveTo(startXPoint,startYPoint);
            mPath.cubicTo(conOneXPoint,conOneYPoint,conTwoXPoint,conTwoYPoint,endXPoint,endYPoint);
            canvas.drawPoint(startXPoint,startYPoint,mPaintCon);
            canvas.drawText("P0",startXPoint-50,startYPoint,mPaintText);
            canvas.drawPoint(endXPoint,endYPoint,mPaintCon);
            canvas.drawText("P3",endXPoint+50,endYPoint,mPaintText);
            canvas.drawPoint(conOneXPoint, conOneYPoint,mPaintCon);
            canvas.drawText("P1", conOneXPoint-50, conOneYPoint,mPaintText);
            canvas.drawPoint(conTwoXPoint, conTwoYPoint,mPaintCon);
            canvas.drawText("P2", conTwoXPoint+50, conTwoYPoint,mPaintText);
    
            canvas.drawLine(startXPoint,startYPoint, conOneXPoint, conOneYPoint,mPaintCon);
            canvas.drawLine(conOneXPoint, conOneYPoint,conTwoXPoint,conTwoYPoint,mPaintCon);
            canvas.drawLine(conTwoXPoint, conTwoYPoint,endXPoint,endYPoint,mPaintCon);
            canvas.drawPath(mPath,mPaint);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_POINTER_DOWN:
                    isPointDown = true;
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    isPointDown = false;
                    break;
                case MotionEvent.ACTION_MOVE:
                    conOneXPoint = event.getX(0);
                    conOneYPoint = event.getY(0);
                    if (isPointDown) {
                        conTwoXPoint = event.getX(1);
                        conTwoYPoint = event.getY(1);
                    }
                    invalidate();
                    break;
    
            }
            return true;
    
        }
    }
    

    我们两个手指一起操作来对贝塞尔三阶曲线进行各种男人的撕扯吧!我不知道使用什么东西来录制屏幕,只能给大家上一张经过我拉扯后的图。

    贝塞尔曲线图

    好了,这次这篇就到这里吧,请大家继续关注我,以后还会去更新贝塞尔曲线的文章。

    题外话:如果谁知道用什么软件可以录制手机屏幕并生成gif图的可以在下方留言。 哈哈,好的我们下期再见。

    相关文章

      网友评论

      • Zeller:用chrome插件vysor在电脑上调试真机,然后用电脑上的录屏工具😬
        邢皓翔: @Zeller 感谢
        Zeller: @邢皓翔 不用,电脑上装了vysor之后就可以在电脑上实时看到手机上的画面,你可以搜索一下。
        邢皓翔:@Zeller 手机上也需要下载Chrome?

      本文标题:Android贝塞尔曲线——曲线进阶

      本文链接:https://www.haomeiwen.com/subject/kdvobttx.html