Android自定义控件Path贝塞尔曲线
这篇文主要说Path绘制曲线,就是曲线中非常有名的贝赛尔曲线。
贝赛尔曲线是由法国数学家Pierre Bézier所发明,由此为计算机矢量图形学奠定了基础。它的主要意义在于无论是直线或曲线都能在数学上予以描述。
理解贝塞尔曲线
塞尔曲线由起始点、数据点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。
数据点:确定曲线的起始和结束位置
控制点:确定曲线的弯曲程度
一阶曲线原理:
一阶曲线是没有控制点的,仅有两个数据点(A 和 B),最终效果一个线段。
二阶曲线原理:
二阶曲线由两个数据点(A 和 C),一个控制点(B)来描述曲线状态,大致如下:
上图中红色曲线部分就是传说中的二阶贝塞尔曲线,那么这条红色曲线是如何生成的呢?接下来我们就以其中的一个状态分析一下:
这样获取到的点F就是贝塞尔曲线上的一个点,动态过程如下:
了解贝塞尔曲线相关函数使用方法
一阶曲线:参照上篇文章Path的操作
二阶曲线:二阶曲线是由两个数据点,一个控制点构成,两个数据点是控制贝塞尔曲线开始和结束的位置,比较容易理解,而控制点则是控制贝塞尔的弯曲状态,相对来说比较难以理解,所以本示例重点在于理解贝塞尔曲线弯曲状态与控制点的关系。直接上代码:
public class BezierTwo extends View {
private Paint mPaint;
private int centerX, centerY;
private PointF start, end, control; //起点,结束点,控制点
public BezierTwo(Context context) {
super(context);
init();
}
public BezierTwo(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public BezierTwo(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(8);
//初始化起点,结束点,控制点
start = new PointF(0, 0);
end = new PointF(0, 0);
control = new PointF(0, 0);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
centerX = w / 2;
centerY = h / 2;
//重新设置起点,结束点和控制点的位置
start.x = centerX - 200;
start.y = centerY;
end.x = centerY + 200;
end.y = centerY;
control.x = centerX;
control.y = centerY - 100;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//根据触摸点更新控制点,并重绘
control.x = event.getX();
control.y = event.getY();
invalidate();
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制数据点和控制点
mPaint.setColor(Color.GRAY);
mPaint.setStrokeWidth(20);
canvas.drawPoint(start.x, start.y, mPaint);
canvas.drawPoint(end.x, end.y, mPaint);
canvas.drawPoint(control.x, control.y, mPaint);
//绘制辅助线
mPaint.setStrokeWidth(4);
canvas.drawLine(start.x,start.y,control.x,control.y,mPaint);
canvas.drawLine(end.x,end.y,control.x,control.y,mPaint);
//绘制贝赛尔曲线
mPaint.setStrokeWidth(8);
mPaint.setColor(Color.RED);
Path path=new Path();
path.moveTo(start.x,start.y);
path.quadTo(control.x,control.y,end.x,end.y);
canvas.drawPath(path,mPaint);
}
}
为了更直观,上图还绘制了控制点和辅助线,从效果图可以看出,贝赛尔曲线是有类似于橡皮筋的效果,所以经常用于绘制一些具有弹性的效果中。