关于贝塞尔曲线的故事

概述

  • 在开始本故事的以前,先来介绍下故事的背景。话说几百年前,从天而降一座神山,远远看去像一天光滑的丝带,它的名字叫作:“贝塞尔曲线"。有大法师预言登上这座神山能够发现天地大秘可是前途艰险。

定义

  • 摘自百度百科android

    贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。通常的矢量图形软件经过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,咱们在绘图工具上看到的钢笔工具就是来作这种矢量曲线的。
    “贝赛尔曲线”是由法国数学家Pierre Bézier所发明,由此为计算机矢量图形学奠基了基础。它的主要意义在于不管是直线或曲线都能在数学上予以描述。canvas

公式

  • 因为应用用到主要以二阶贝塞尔曲线为主,贴下二阶的公式:api

    二次方公式
    二次方贝兹曲线的路径由给定点P0、P一、P2的函数B(t):
    ide

如何应用?

  • 为了前往"贝塞尔曲线山",向那些从前登上神山的老前辈请教;

所需的Android知识

  • 画笔(paint),路径(path),画布(canvas)类的api要熟悉函数

  • View绘制的生命周期工具

    简单来看:测量-measure 摆放-layout 绘制-draw测试

  • Android触摸事件code

    这里须要了解onTouchEvent方法能够捕捉到触屏的事件blog

用手势画光滑的曲线

  • 路途艰险,在这里我碰到了大白虎,史前巨兽猛犸象,海天鲲鹏,经历了生死考验终于登上神山,恍然大悟,天地大秘原来在此。生命周期

  • 让咱们想想画东西须要什么?答案:一块白板,一只笔。
  • 这里的关键是手势与光滑,处理手势的话就是前面讲的重写Android触摸事件,聪明的你必定想到了经过二阶贝塞尔曲线去作到光滑。
  • 画一条二阶贝塞尔曲线须要3个点,两个数据点一个控制点,那么手势落下的点--起始点(x1,y1)与不断移动的手的触点是数据点,控制点须要本身创造,那线段的中点是最好计算的,假设第一个手滑动到的点(x2,y2),那么中点就是((x1+x2)/2,(y1+y2)/2)。
  • 重写Android触摸事件须要捕捉MOVE类型与DOWN类型的事件,DOWN类型的事件中须要记录起始点的位置,而MOVE类型事件须要缓冲上一次移动的位置。

  • 1.声明控制点,曲线,起始点,以及断定滑动的距离
private  Paint controlPaint;

    private Path mCurrentPath;

    private float startPointX;
    private float startPointY;
    //画贝塞尔曲线的标识--能够自定义值
    private float offset = ViewConfiguration.get(getContext()).getScaledTouchSlop();
  • 2.初始化画笔与路径
public PaintBeSaiErView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        //创建路径
        mCurrentPath = new Path();
        //绘制时抗锯齿
        controlPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //设置画笔样式
        controlPaint.setStyle(Paint.Style.STROKE);
        //设置画笔的粗细
        controlPaint.setStrokeWidth(8);
        //设置画笔颜色
        controlPaint.setColor(Color.RED);

    }
  • 3.重写onTouchEvent,记录手势起始点与移动位置并绘制贝塞尔曲线,经过invalidate方法更新UI视图
@Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //为了方便测试,每次下落以前清空路径
                mCurrentPath.reset();
                float x = event.getX();
                float y = event.getY();
                startPointX = x;
                startPointY = y;
                //移动到起始点
                mCurrentPath.moveTo(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                float curX= event.getX();
                float curY= event.getY();
                float preX= startPointX;
                float preY= startPointY;
                if(Math.abs(preX-curX)>=offset||Math.abs(preX-curY)>=offset) {
                    mCurrentPath.quadTo((curX + preX) / 2, (curY + preY) / 2, curX, curY);
                    startPointX = curX;
                    startPointY = curY;
                }
                invalidate();
                break;
        }
        return  true;
    }
  • 4.下面对比使用线段画lineTo(curX, curY)与贝塞尔曲线画quadTo(avgX,avgY)的效果

    左图为线段画的,右图为贝塞尔曲线画的,看起来更圆润!why?其实,用线段画基本上看是一个折线图,而贝塞尔函数画是一段段曲线

  • 固然,贝塞尔曲线的应用十分普遍,上面是简单的例子,后面将讲如何应用模拟翻页。

总结

  • 总觉得登上神山才是最大的收获,原来一路走来更有收获。
  • 去了解一个事物的时候,要善于思考,记忆中愈来愈深入的,每每思考的越透彻。
相关文章
相关标签/搜索