前言
前面我们讲解过贝塞尔曲线的原理和公式
这篇博客,我们通过代码来实现任意阶的贝塞尔曲线,并通过动画演示其形成过程
能把这份代码完成吃透,说明对贝塞尔曲线已经完全了解了
效果图
核心代码
package com.android.architecture;
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;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
//一个演示N阶贝塞尔曲线形成过程的控件
@SuppressWarnings("all")
public class BezierDemoView extends View {
//贝塞尔曲线取样数
final int BEZIER_SAMPLE_COUNT = 1000;
//控制点半径
final int CONTROL_POINT_RADIUS = 6;
//所有线条的宽度
final int CONTROL_LINE_WIDTH = 6;
//贝塞尔曲线最大最小阶数
final int MIN_LEVEL = 1;
final int MAX_LEVEL = 7;
//切线颜色,七阶曲线共有六条切线,六种颜色
final String[] TANGENT_LINE_COLORS = {"#7FFF00", "#7A67EE", "#EE82EE", "#FFD700", "#1C86EE", "#8B8B00"};
//贝塞尔曲线路径
Path bezierPath = new Path();
PointF bezierPoint;
List bezierPoints;
//贝塞尔曲线阶数
int bezierLevel = 4;
//贝塞尔曲线移动速率,每帧跳过几个点
int bezierMoveRate = 5;
//当前帧贝塞尔曲线上点的Index
int bezierPointIndex = 0;
//控制点
List controlPoints;
//每阶切线的所有切线点
//贝塞尔曲线的取点过程,就是一个位置比率变化和切线逐级降阶的过程
//这个不懂的,可以先去网上补充下这方面的基础
List roundTanPoints;
//所有帧的切线点
//上面的点是单帧的,这个是全部数据
List frameTanPoints;
//画布大小
int w = 0;
int h = 0;
//控制线画笔
Paint controlLinePaint;
//控制点画笔
Paint controlPointPaint;
//控制点名称画笔
Paint controlTextPaint;
//切线画笔
Paint tangentLinePaint;
//贝塞尔曲线画笔
Paint bezierPaint;
//当前贝塞尔点画笔
Paint currentPointPaint;
//状态锁,防止数据未准备完毕就开始绘制
final Object readyLock = new Object();
//动画暂停中
boolean isAnimationPaused = false;
//循环显示
boolean loop = false;
public BezierDemoView(Context context) {
this(context, null);
}
public BezierDemoView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
init();
}
protected void init() {
//控制线画笔
controlLinePaint = new Paint();
controlLinePaint.setAntiAlias(true);
controlLinePaint.setColor(Color.LTGRAY);
controlLinePaint.setStrokeWidth(CONTROL_LINE_WIDTH);
controlLinePaint.setStyle(Paint.Style.FILL);
controlLinePaint.setStrokeCap(Paint.Cap.ROUND);
//控制点画笔
controlPointPaint = new Paint();
controlPointPaint.setAntiAlias(true);
controlPointPaint.setColor(Color.BLACK);
controlPointPaint.setStyle(Paint.Style.STROKE);
//控制点名称画笔
controlTextPaint = new Paint();
controlTextPaint.setAntiAlias(true);
controlTextPaint.setColor(Color.BLACK);
controlTextPaint.setTextSize(40);
//切线画笔
tangentLinePaint = new Paint();
tangentLinePaint.setAntiAlias(true);
tangentLinePaint.setColor(Color.parseColor(TANGENT_LINE_COLORS[0]));
tangentLinePaint.setStrokeWidth(CONTROL_LINE_WIDTH);
tangentLinePaint.setStyle(Paint.Style.FILL);
//贝塞尔曲线画笔
bezierPaint = new Paint();
bezierPaint.setAntiAlias(true);
bezierPaint.setColor(Color.RED);
bezierPaint.setStrokeWidth(CONTROL_LINE_WIDTH);
bezierPaint.setStyle(Paint.Style.STROKE);
//当前贝塞尔点画笔
currentPointPaint = new Paint();
currentPointPaint.setAntiAlias(true);
currentPointPaint.setColor(Color.RED);
currentPointPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onDraw(Canvas canvas) {
synchronized (readyLock) {
//没有数据,返回
if (bezierPoints == null) {
postInvalidateDelayed(20);
return;
}
//首帧将Path移动到起点
if (bezierPath.isEmpty()) {
PointF startPoint = bezierPoints.get(0);
bezierPath.moveTo(startPoint.x, startPoint.y);
}
//画控制点之间的连线
for (int i = 0; i 0)
canvas.drawLine(controlPoints.get(i - 1).x, controlPoints.get(i - 1).y, p.x, p.y, controlLinePaint);
}
//画控制点
for (int i = 0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?