前言:
好久没写技术博客了。android很多酷炫的自定义VIew效果和贝塞尔曲线相关,像水波纹效、火箭效果等,从本篇开始将研究和使用贝塞尔曲线以及xfermode。相应的效果,以后也会以gif图片展示,更为直观。
概要:
本篇文章主要介绍贝塞尔曲线,以及对于二阶和三阶贝塞尔曲线的简单使用。
正文:
1,什么是贝塞尔曲线
贝塞尔曲线,又称贝兹曲线或者贝济埃曲线,是应用于二位图形应用程序的数学曲线。贝塞尔曲线是由线段和节点组成的,节点是可以拖动的支点,线段像可以伸缩的橡皮筋。是计算机图形学当中比较重要的参数曲线。
这里盗两张图,我们结合常用的一阶贝塞尔曲线、二阶贝塞尔曲线和三阶贝塞尔曲线来理解下:
1)一阶贝塞尔曲线:
一阶贝塞尔曲线展现的是一条两点之间的直线。B(t)是t时间下,点的坐标,P0为起点、P1为终点。
t时间点的坐标 B(t)=P0 + (P1 - P0)*t = (1-t)*P0 + P1*t
2)二阶贝塞尔曲线:
二阶贝塞尔曲线展现的是一条抛物线。P0至P1之间的连续点Q0,描述一条线段,P1至P2之间的连续点Q1,描述一条线段,Q0至Q1之间的连续点B(t),描述一条二阶贝塞尔曲线。如图Q0视为绿色线段在P0~P1上的点,Q1视为绿色线段在P1~P2上的点。
附上超吃藕手写推算过程:
3)三阶贝塞尔曲线:
具体原理以及推算公式可以参照二阶贝塞尔曲线的推算方式。
贝塞尔曲线通用公式:
说明:P0点到P1点的连续点直线和贝塞尔曲线相切。
2,贝塞尔曲线在android中的相关使用
Android中的Path类提供了绘制贝塞尔曲线的方法。
1)二阶贝塞尔曲线:
//设置Path移动到起始位置100,300 mPath.moveTo(100,300); //设置辅助点250,300 设置终点400,300 mPath.quadTo(250,300,400,300);效果如图:
现在知识一条直线,实现抛物线的效果,我们需要结合onTouch事件,将辅助点的坐标改为动态的:
@Override protected void onDraw(Canvas canvas) { mPath.reset(); mPaint.setColor(Color.parseColor("#ff0000")); mPaint.setStrokeWidth(5); mPaint.setStyle(Paint.Style.STROKE); //设置Path移动到起始位置100,300 mPath.moveTo(100,300); //设置辅助点250,300 设置终点400,300 mPath.quadTo(supX,supY,400,300); canvas.drawPath(mPath,mPaint); super.onDraw(canvas); }
@Override public boolean onTouchEvent(MotionEvent event) { switch(event.getAction()){ case MotionEvent.ACTION_MOVE: supX = event.getX(); supY = event.getY(); invalidate(); break; default: break; } return true; }此时的效果:
现在曲线随着辅助点变化,但是辅助点的位置不够直观,没有办法看出辅助点和抛物线的关系,下面把辅助点显示出来。
canvas.drawPoint(supX,supY,mPaint);现在我们也可以看到辅助点了:
2)三阶贝塞尔曲线:
使用Path类中的cubilTo方法。
cubicTo(float x1, float y1, float x2, float y2,float x3, float y3)x1,y1是第一个辅助点的坐标;x2,y2是第二个辅助点的坐标;x3,y3是终点的坐标。
直接绘制出效果和辅助点:
@Override protected void onDraw(Canvas canvas) { mPath.reset(); mPaint.setColor(Color.parseColor("#ff0000")); mPaint.setStrokeWidth(10); mPaint.setStyle(Paint.Style.STROKE); //设置Path移动到起始位置100,300 mPath.moveTo(100,300); //设置辅助点250,500 设置辅助点550,150 设置终点800,300 mPath.cubicTo(250,500,550,150,800,300); canvas.drawPath(mPath,mPaint); //绘制第一个辅助点 canvas.drawPoint(250,500,mPaint); //绘制第二个辅助点 canvas.drawPoint(550,150,mPaint); super.onDraw(canvas); }
关于贝塞尔曲线的使用,实现水波纹等效果,会在下一篇介绍。