——来自百度百科

XMind 示例

n 阶贝塞尔曲线可如下推断。给定点P0、P1、…、Pn，其贝塞尔曲线即：

Android上实现贝赛尔曲线

Path.moveTo(float x, float y) // Path的初始点

Path.lineTo(float x, float y) // 线性公式的贝赛尔曲线, 其实就是直线

Path.quadTo(float x1, float y1, float x2, float y2) // 二阶贝赛尔曲线

Path.cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) // 三阶贝赛尔曲线

...

package com.example.pc.mybeziercurveview.view;

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 Deeson on 2017/5/24.

*/

private Paint mPaint;

private Path mPath;

private int centerX,centerY;

private PointF start,end,control;

super(context);

init();

}

public MyBezierCurveQuadratic(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public MyBezierCurveQuadratic(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

private void init() {

mPaint = new Paint();

mPath = new Path();

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);

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 = centerX + 200;

end.y = centerY;

control.x = centerX;

control.y = centerY - 100;

}

@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(control.x, control.y, end.x, end.y, mPaint);

//绘制二阶贝塞尔曲线

mPaint.setColor(Color.RED);

mPaint.setStrokeWidth(8);

mPath.reset();

mPath.moveTo(start.x,start.y);

canvas.drawPath(mPath,mPaint);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

case MotionEvent.ACTION_MOVE:

control.x = event.getX();

control.y = event.getY();

invalidate();

break;

}

return true;

}

}

//辅助线坐标点

process1.x = (1 - t) * start.x + t * control.x;

process1.y = (1 - t) * start.y + t * control.y;

process2.x = (1 - t) * control.x + t * end.x;

process2.y = (1 - t) * control.y + t * end.y;

//贝塞尔曲线通用函数

x = (1 - t) * process1.x + t * process2.x;

y = (1 - t) * process1.y + t * process2.y;

mPath.lineTo(x, y);

//绘制数据点和控制点

mCanvas.drawPoint(start.x, start.y, mPointPaint);

mCanvas.drawPoint(control.x, control.y, mPointPaint);

mCanvas.drawPoint(end.x, end.y, mPointPaint);

//绘制数据点和控制点的连线

mCanvas.drawLine(start.x, start.y, control.x, control.y, mLinePaint);

mCanvas.drawLine(control.x, control.y, end.x, end.y, mLinePaint);

//绘制辅助线和辅助点

mCanvas.drawLine(process1.x, process1.y, process2.x, process2.y, mAssistLinePaint);

mCanvas.drawPoint(process1.x,process1.y,mAssistPointPaint);

mCanvas.drawPoint(process2.x,process2.y,mAssistPointPaint);

//绘制二阶贝塞尔曲线的当前点

mCanvas.drawPoint(x, y, mPointPaint);

//绘制二阶贝塞尔曲线

mCanvas.drawPath(mPath, mPaint);

package com.example.pc.mybeziercurveview.view;

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.SurfaceHolder;

import android.view.SurfaceView;

/**

* 二阶

* Created by Deeson on 2017/5/24.

*/

public class QuadraticBezierShowView extends SurfaceView implements SurfaceHolder.Callback, Runnable {

//分别对应贝塞尔曲线、点、数据点和控制点之间的线、辅助线、辅助点

private Paint mPaint, mPointPaint, mLinePaint, mAssistLinePaint,mAssistPointPaint;

//绘制贝塞尔曲线的path

private Path mPath;

//布局的中心点

private int centerX, centerY;

//分别对应贝塞尔曲线的起点、终点、控制点、辅助线的起点、终点

private PointF start, end, control, process1, process2;

private SurfaceHolder mHolder;

//用于绘图的canvas

private Canvas mCanvas;

//子线程标志位

private boolean mIsDrawing;

float x = 0;//贝塞尔曲线的实时点x坐标

float y = 0;//贝塞尔曲线的实时点y坐标

float t = 0;//实施进度，0<=t<=1

super(context);

init();

}

public QuadraticBezierShowView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public QuadraticBezierShowView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

private void init() {

mPaint = new Paint();

mPath = new Path();

mPaint.setColor(Color.RED);

mPaint.setStrokeWidth(5);

mPaint.setStyle(Paint.Style.STROKE);

mPaint.setTextSize(60);

mPointPaint = new Paint();

mPointPaint.setColor(Color.BLACK);

mPointPaint.setStrokeWidth(10);

mPointPaint.setStyle(Paint.Style.STROKE);

mLinePaint = new Paint();

mLinePaint.setColor(Color.GRAY);

mLinePaint.setStrokeWidth(4);

mLinePaint.setStyle(Paint.Style.STROKE);

mAssistLinePaint = new Paint();

mAssistLinePaint.setColor(Color.GREEN);

mAssistLinePaint.setStrokeWidth(4);

mAssistLinePaint.setStyle(Paint.Style.STROKE);

mAssistPointPaint = new Paint();

mAssistPointPaint.setColor(Color.GREEN);

mAssistPointPaint.setStrokeWidth(10);

mAssistPointPaint.setStyle(Paint.Style.FILL);

start = new PointF(0, 0);

end = new PointF(0, 0);

control = new PointF(0, 0);

process1 = new PointF(0, 0);

process2 = new PointF(0, 0);

mHolder = getHolder();

setFocusable(true);

setFocusableInTouchMode(true);

this.setKeepScreenOn(true);

}

@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;

control.x = centerX - 50;

control.y = centerY - 300;

x = start.x;

y = start.y;

mPath.moveTo(x, y);

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

mIsDrawing = true;

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

mIsDrawing = false;

}

@Override

public void run() {

while (mIsDrawing) {

draw();

if (t <= 1) {

t += 0.003;

//辅助线坐标点

process1.x = (1 - t) * start.x + t * control.x;

process1.y = (1 - t) * start.y + t * control.y;

process2.x = (1 - t) * control.x + t * end.x;

process2.y = (1 - t) * control.y + t * end.y;

//贝塞尔曲线通用函数

x = (1 - t) * process1.x + t * process2.x;

y = (1 - t) * process1.y + t * process2.y;

//二阶贝塞尔曲线函数

// x = (float) (Math.pow((1 - t), 2) * start.x + 2 * t * (1 - t) * control.x + Math.pow(t, 2) * end.x);

// y = (float) (Math.pow((1 - t), 2) * start.y + 2 * t * (1 - t) * control.y + Math.pow(t, 2) * end.y);

mPath.lineTo(x, y);

} else {

mIsDrawing = false;

}

}

}

private void draw() {

try {

mCanvas = mHolder.lockCanvas();

mCanvas.drawColor(Color.WHITE);

//绘制数据点和控制点

mCanvas.drawPoint(start.x, start.y, mPointPaint);

mCanvas.drawPoint(control.x, control.y, mPointPaint);

mCanvas.drawPoint(end.x, end.y, mPointPaint);

//绘制数据点和控制点的连线

mCanvas.drawLine(start.x, start.y, control.x, control.y, mLinePaint);

mCanvas.drawLine(control.x, control.y, end.x, end.y, mLinePaint);

//绘制辅助线和辅助点

mCanvas.drawLine(process1.x, process1.y, process2.x, process2.y, mAssistLinePaint);

mCanvas.drawPoint(process1.x,process1.y,mAssistPointPaint);

mCanvas.drawPoint(process2.x,process2.y,mAssistPointPaint);

//绘制二阶贝塞尔曲线的当前点

mCanvas.drawPoint(x, y, mPointPaint);

//绘制二阶贝塞尔曲线

mCanvas.drawPath(mPath, mPaint);

} catch (Exception e) {

e.printStackTrace();

} finally {

if (null != mCanvas) {

mHolder.unlockCanvasAndPost(mCanvas);

}

}

}

}

package com.example.pc.mybeziercurveview.view;

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 Deeson on 2017/5/24.

*/

public class MyBezierCurveCubic extends View{

private Paint mPaint;

private Path mPath;

private int centerX,centerY;

private PointF start,end,control1,control2;

public static final int CONTROL_ONE = 0;

public static final int CONTROL_TWO = 1;

private int control = CONTROL_ONE;

public MyBezierCurveCubic(Context context) {

super(context);

init();

}

public MyBezierCurveCubic(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public MyBezierCurveCubic(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

private void init() {

mPaint = new Paint();

mPath = new Path();

mPaint.setColor(Color.BLACK);

mPaint.setStrokeWidth(8);

mPaint.setStyle(Paint.Style.STROKE);

start = new PointF(0,0);

end = new PointF(0,0);

control1 = new PointF(0,0);

control2 = 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 = centerX + 200;

end.y = centerY;

control1.x = centerX - 200;

control1.y = centerY - 200;

control2.x = centerX + 200;

control2.y = centerY + 200;

}

@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(control1.x,control1.y,mPaint);

canvas.drawPoint(control2.x, control2.y, mPaint);

//绘制辅助线

mPaint.setStrokeWidth(4);

canvas.drawLine(start.x, start.y, control1.x, control1.y, mPaint);

canvas.drawLine(control1.x, control1.y, control2.x, control2.y, mPaint);

canvas.drawLine(control2.x, control2.y, end.x, end.y, mPaint);

//绘制三阶贝塞尔曲线

mPaint.setColor(Color.RED);

mPaint.setStrokeWidth(8);

mPath.reset();

mPath.moveTo(start.x,start.y);

mPath.cubicTo(control1.x,control1.y,control2.x,control2.y,end.x,end.y);

canvas.drawPath(mPath,mPaint);

}

public void setControl(int control){

this.control = control;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

case MotionEvent.ACTION_MOVE:

if(control == CONTROL_ONE){

control1.x = event.getX();

control1.y = event.getY();

}else{

control2.x = event.getX();

control2.y = event.getY();

}

invalidate();

break;

}

return true;

}

}

package com.example.pc.mybeziercurveview.view;

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.SurfaceHolder;

import android.view.SurfaceView;

/**

* 三阶

* Created by Deeson on 2016/7/12.

*/

public class CubicBezierShowView extends SurfaceView implements SurfaceHolder.Callback, Runnable {

//分别对应贝塞尔曲线、点、数据点和控制点之间的线、第一层辅助线、第一层辅助点、第二层辅助线、第二层辅助点

private Paint mPaint, mPointPaint, mLinePaint, mAssistLine1Paint, mAssistPoint1Paint, mAssistLine2Paint, mAssistPoint2Paint;

//绘制贝塞尔曲线的path

private Path mPath;

//布局的中心点

private int centerX, centerY;

//分别对应三阶贝塞尔曲线的起点、终点、控制点

private PointF start, end, control1, control2;

//第一层辅助线的3个端点(相当于动态的二阶贝塞尔曲线的起点，控制点，终点)

private PointF process1, process2, process3;

//第二层辅助线的起点和终点

private PointF secondProcess1, secondProcess2;

private SurfaceHolder mHolder;

//用于绘图的canvas

private Canvas mCanvas;

//子线程标志位

private boolean mIsDrawing;

float x = 0;//贝塞尔曲线的实时点x坐标

float y = 0;//贝塞尔曲线的实时点y坐标

float t = 0;//实施进度，0<=t<=1

public CubicBezierShowView(Context context) {

super(context);

init();

}

public CubicBezierShowView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public CubicBezierShowView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

private void init() {

//贝塞尔曲线

mPaint = new Paint();

mPath = new Path();

mPaint.setColor(Color.RED);

mPaint.setStrokeWidth(5);

mPaint.setStyle(Paint.Style.STROKE);

mPaint.setTextSize(60);

//点

mPointPaint = new Paint();

mPointPaint.setColor(Color.BLACK);

mPointPaint.setStrokeWidth(10);

mPointPaint.setStyle(Paint.Style.STROKE);

//数据点和控制点的连线

mLinePaint = new Paint();

mLinePaint.setColor(Color.GRAY);

mLinePaint.setStrokeWidth(4);

mLinePaint.setStyle(Paint.Style.STROKE);

//第一层辅助线

mAssistLine1Paint = new Paint();

mAssistLine1Paint.setColor(Color.GREEN);

mAssistLine1Paint.setStrokeWidth(4);

mAssistLine1Paint.setStyle(Paint.Style.STROKE);

//第一层辅助点

mAssistPoint1Paint = new Paint();

mAssistPoint1Paint.setColor(Color.GREEN);

mAssistPoint1Paint.setStrokeWidth(10);

mAssistPoint1Paint.setStyle(Paint.Style.FILL);

//第二层辅助线

mAssistLine2Paint = new Paint();

mAssistLine2Paint.setColor(Color.BLUE);

mAssistLine2Paint.setStrokeWidth(4);

mAssistLine2Paint.setStyle(Paint.Style.STROKE);

//第二层辅助线

mAssistPoint2Paint = new Paint();

mAssistPoint2Paint.setColor(Color.BLUE);

mAssistPoint2Paint.setStrokeWidth(10);

mAssistPoint2Paint.setStyle(Paint.Style.FILL);

//三阶贝塞尔曲线的起点终点

start = new PointF(0, 0);

end = new PointF(0, 0);

//三阶贝塞尔曲线的两个控制点

control1 = new PointF(0, 0);

control2 = new PointF(0, 0);

//第一层辅助线的三个端点

process1 = new PointF(0, 0);

process2 = new PointF(0, 0);

process3 = new PointF(0, 0);

//第二层辅助线的两个端点

secondProcess1 = new PointF(0, 0);

secondProcess2 = new PointF(0, 0);

mHolder = getHolder();

setFocusable(true);

setFocusableInTouchMode(true);

this.setKeepScreenOn(true);

}

@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;

control1.x = centerX - 150;

control1.y = centerY - 300;

control2.x = centerX + 170;

control2.y = centerY - 340;

x = start.x;

y = start.y;

mPath.moveTo(x, y);

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

mIsDrawing = true;

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

mIsDrawing = false;

}

@Override

public void run() {

while (mIsDrawing) {

draw();

if (t <= 1) {

t += 0.003;

//重点在这里

bezierDraw();

mPath.lineTo(x, y);

} else {

mIsDrawing = false;

}

}

}

private void draw() {

try {

mCanvas = mHolder.lockCanvas();

mCanvas.drawColor(Color.WHITE);

//绘制数据点和控制点

mCanvas.drawPoint(start.x, start.y, mPointPaint);

mCanvas.drawPoint(control1.x, control1.y, mPointPaint);

mCanvas.drawPoint(control2.x, control2.y, mPointPaint);

mCanvas.drawPoint(end.x, end.y, mPointPaint);

//绘制数据点和控制点的连线

mCanvas.drawLine(start.x, start.y, control1.x, control1.y, mLinePaint);

mCanvas.drawLine(control1.x, control1.y, control2.x, control2.y, mLinePaint);

mCanvas.drawLine(control2.x, control2.y, end.x, end.y, mLinePaint);

//绘制第一层辅助线和辅助点

mCanvas.drawLine(process1.x, process1.y, process2.x, process2.y, mAssistLine1Paint);

mCanvas.drawLine(process2.x, process2.y, process3.x, process3.y, mAssistLine1Paint);

mCanvas.drawPoint(process1.x, process1.y, mAssistPoint1Paint);

mCanvas.drawPoint(process2.x, process2.y, mAssistPoint1Paint);

mCanvas.drawPoint(process3.x, process3.y, mAssistPoint1Paint);

//绘制第二层辅助线和辅助点

mCanvas.drawLine(secondProcess1.x, secondProcess1.y, secondProcess2.x, secondProcess2.y, mAssistLine2Paint);

mCanvas.drawPoint(secondProcess1.x, secondProcess1.y, mAssistPoint2Paint);

mCanvas.drawPoint(secondProcess2.x, secondProcess2.y, mAssistPoint2Paint);

//绘制三阶贝塞尔曲线的当前点

mCanvas.drawPoint(x, y, mPointPaint);

//绘制三阶贝塞尔曲线

mCanvas.drawPath(mPath, mPaint);

} catch (Exception e) {

e.printStackTrace();

} finally {

if (null != mCanvas) {

mHolder.unlockCanvasAndPost(mCanvas);

}

}

}

private void bezierDraw() {

//第一层辅助线坐标点

process1.x = (1 - t) * start.x + t * control1.x;

process1.y = (1 - t) * start.y + t * control1.y;

process2.x = (1 - t) * control1.x + t * control2.x;

process2.y = (1 - t) * control1.y + t * control2.y;

process3.x = (1 - t) * control2.x + t * end.x;

process3.y = (1 - t) * control2.y + t * end.y;

//第二层辅助线坐标点

secondProcess1.x = (1 - t) * process1.x + t * process2.x;

secondProcess1.y = (1 - t) * process1.y + t * process2.y;

secondProcess2.x = (1 - t) * process2.x + t * process3.x;

secondProcess2.y = (1 - t) * process2.y + t * process3.y;

//贝塞尔曲线通用公式

x = (1 - t) * secondProcess1.x + t * secondProcess2.x;

y = (1 - t) * secondProcess1.y + t * secondProcess2.y;

//三阶贝塞尔曲线函数

// x = (float) (Math.pow((1 - t), 3) * start.x + 3 * t * Math.pow((1 - t), 2) * control1.x + 3 * Math.pow(t, 2) * (1 - t) * control2.x + Math.pow(t, 3) * end.x);

// y = (float) (Math.pow((1 - t), 3) * start.y + 3 * t * Math.pow((1 - t), 2) * control1.y + 3 * Math.pow(t, 2) * (1 - t) * control2.y + Math.pow(t, 3) * end.y);

}

}

Demo下载地址 点这里，Demo里还有四阶曲线的展示，可以看看，原理与二阶三阶雷同，就不贴代码了。