什么是贝塞尔曲线?
贝塞尔曲线(Bézier curve
),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。主要结构:起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。
贝塞尔曲线的分类
了解一下贝塞尔曲线,根据影响变量的个数不同,我们可以看到不同类型的曲线。参考资料:http://blog.csdn.net/z82367825/article/details/51599245
一阶贝塞尔曲线(线段):
公式:
意义:由 P0 至 P1 的连续点, 描述的一条线段。
二阶贝塞尔曲线(抛物线):
公式:
原理: 由 P0 至 P1 的连续点 Q0,描述一条线段。
由 P1 至 P2 的连续点 Q1,描述一条线段。
由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。
三阶贝塞尔曲线:
当然还有四阶曲线、五阶曲线......只不过随着变量的增加,复杂维度会越来越高。
贝塞尔曲线代码实现
我们一般使用的是二阶贝塞尔曲线和三阶贝塞尔曲线,从动态图和公式我们可以看出,贝塞尔曲线主要由于三个部分控制:起点,终点,中间的辅助控制点。如何利用这三个点画出贝塞尔曲线,在android自带的Path类中自带了方法,可以帮助我们实现贝塞尔曲线:
需要的有两个类:
第一个类是实现二阶的:
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.view.MotionEvent; import android.view.View; /** * Created by huqing on 2016/6/27. */ public class TwoBezier extends View { private Paint mPaint; private int centerX, centerY; private PointF start, end, fingerPoint; /** * 使用,例: * TwoBezier mBezier = new TwoBezier(this); * setContentView(mBezier); * * @param context */ public TwoBezier(Context context) { super(context); //画笔 mPaint = new Paint(); mPaint.setStrokeWidth(8); mPaint.setStyle(Paint.Style.STROKE); mPaint.setTextSize(60); //三点确定该二阶曲线 start = new PointF(0, 0); end = new PointF(0, 0); fingerPoint = new PointF(0, 0); } /** * 手指触碰时获取当前手指坐标 * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { // 根据触摸位置更新控制点,并提示重绘 fingerPoint.x = event.getX(); fingerPoint.y = event.getY(); invalidate();//调用onDraw方法 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(fingerPoint.x, fingerPoint.y, mPaint); // 绘制辅助线 mPaint.setStrokeWidth(4); canvas.drawLine(start.x, start.y, fingerPoint.x, fingerPoint.y, mPaint); canvas.drawLine(end.x, end.y, fingerPoint.x, fingerPoint.y, mPaint); // 绘制贝塞尔曲线 mPaint.setColor(Color.RED); mPaint.setStrokeWidth(8); //绘制曲线路径 Path path = new Path(); //起点 path.moveTo(start.x, start.y); //关键方法:谷歌封装好的贝塞尔曲线绘制方法quadTo,给出控制点和终点 path.quadTo(fingerPoint.x, fingerPoint.y, end.x, end.y); canvas.drawPath(path, mPaint); } /** * onSizeChanged的启动时间在onDraw之前,初始化该View时获取到长宽 */ @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 = centerX + 200; end.y = centerY; //控制点,就是手指移动的那个点 fingerPoint.x = centerX; fingerPoint.y = centerY - 100; } }
三阶的曲线,具体代码如下:
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * Created by huqing on 2016/6/27. */ public class BezierThree extends View { private Paint mPaint; private int centerX, centerY; private PointF start, end, fingerPointOne, fingerPointTwo; private boolean mode = true; public BezierThree(Context context) { this(context, null); } public BezierThree(Context context, AttributeSet attrs) { super(context, attrs); //画笔 mPaint = new Paint(); mPaint.setColor(Color.BLACK); mPaint.setStrokeWidth(8); mPaint.setStyle(Paint.Style.STROKE); mPaint.setTextSize(60); //中间点 start = new PointF(0, 0); end = new PointF(0, 0); fingerPointOne = new PointF(0, 0); fingerPointTwo = 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 = 10; start.y = centerY; end.x = w - 10; end.y = centerY; fingerPointOne.x = centerX; fingerPointOne.y = centerY - 100; fingerPointTwo.x = centerX; fingerPointTwo.y = centerY - 100; } @Override public boolean onTouchEvent(MotionEvent event) { // 根据触摸位置更新控制点,并提示重绘 if (mode) { fingerPointOne.x = event.getX(); fingerPointOne.y = event.getY(); } else { fingerPointTwo.x = event.getX(); fingerPointTwo.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(fingerPointOne.x, fingerPointOne.y, mPaint); canvas.drawPoint(fingerPointTwo.x, fingerPointTwo.y, mPaint); // 绘制辅助线 mPaint.setStrokeWidth(4); canvas.drawLine(start.x, start.y, fingerPointOne.x, fingerPointOne.y, mPaint); canvas.drawLine(fingerPointOne.x, fingerPointOne.y, fingerPointTwo.x, fingerPointTwo.y, mPaint); canvas.drawLine(fingerPointTwo.x, fingerPointTwo.y, end.x, end.y, mPaint); // 绘制贝塞尔曲线 mPaint.setColor(Color.RED); mPaint.setStrokeWidth(8); Path path = new Path(); //起点 path.moveTo(start.x, start.y); //贝塞尔曲线中间途径的点 path.cubicTo(fingerPointOne.x, fingerPointOne.y, fingerPointTwo.x, fingerPointTwo.y, end.x, end.y); canvas.drawPath(path, mPaint); } } 最后调用就好了 setContentView(new BezierThree(this));
奉 (2018/01/16 16:59:35)回复
一辈子只做好一件事!我是有多么的大方吖!哈哈