前言:
好久没写技术博客了。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 方法。
x1,y1 是第一个辅助点的坐标;x2,y2 是第二个辅助点的坐标;x3,y3 是终点的坐标。
- cubicTo(float x1, float y1, float x2, float y2,float x3, float 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);
- }
关于贝塞尔曲线的使用,实现水波纹等效果,会在下一篇介绍。
来源: http://www.bubuko.com/infodetail-1963467.html