Android 高级UI10 Path及其贝塞尔曲线

发布时间:2021年10月04日 阅读:14 次

Path工具类:用来记录线条的轨迹路径 canvas.draw(path,paint); 贝塞尔曲线 现实生活当中,任何的曲线和曲面都可以用贝塞尔公式来解决。 比如:

1.设计贝塞尔曲线或者贝塞尔曲线效果图
2.怎么去得到贝塞尔曲线的几个要素(比如二阶贝塞尔:p0初始位置,p1拐点,p2结束点)
p1拐点如何确定,可以通过工具来确定,比如Photoshop点钢笔工具等

原理和简单推导(以三阶为例):

P0、P02、P2是一条抛物线上顺序三个不同的点。过P0和P2点的两切线交于P1点,在P02点的切线交P0P1和P2P1于P01和P11,则如下比例成立:

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第1张  

这是所谓抛物线的三切线定理。

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第2张  

P0,P2固定,引入参数t,令上述比值为t:(1-t),即有:

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第3张  

t从0变到1,第一、二式就分别表示控制二边形的第一、二条边,它们是两条一次Bezier曲线。将一、二式代入第三式得:

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第4张  

t从0变到1时,它表示了由三顶点P0、P1、P2三点定义的一条二次Bezier曲线。

并且表明:

二次Bezier曲线P02可以定义为分别由前两个顶点(P0,P1)和后两个顶点(P1,P2)决定的一次Bezier曲线的线性组合

依次类推,

由四个控制点定义的三次Bezier曲线P03可被定义为分别由(P0,P1,P2)和(P1,P2,P3)确定的二条二次Bezier曲线的线性组合,由(n+ 1)个控制点P**i(i=0,1,...,n)定义的n次Bezier曲线P0n可被定义为分别由前、后n个控制点定义的两条(n-1)次Bezier曲线P0n-1与P1*n-*1的线性组合:

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第5张  

由此得到Bezier曲线的递推计算公式

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第6张  

这就是这就是de Casteljau算法,可以简单阐述三阶贝塞尔曲线原理。

Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。 曲线定义:起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。 1962年,法国数学家Pierre Bézier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名,称为贝塞尔曲线。

以下公式中:B(t)为t时间下 点的坐标;

P0为起点,Pn为终点,Pi为控制点

一阶贝塞尔曲线(线段):

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第7张       Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第8张  

意义:由 P0 至 P1 的连续点, 描述的一条线段

二阶贝塞尔曲线(抛物线):

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第9张       Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第10张  

原理:由 P0 至 P1 的连续点 Q0,描述一条线段。
由 P1 至 P2 的连续点 Q1,描述一条线段。
由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。

经验:P1-P0为曲线在P0处的切线。

三阶贝塞尔曲线:

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第11张       Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第12张  

通用公式:

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第13张  

高阶贝塞尔曲线:

4阶曲线:

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第14张  

5阶曲线:

Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第15张  

二阶贝塞尔曲线

public class WaveView extends View {     private Paint paint;     private Path path;     public WaveView(Context context) {         super(context);     }     public WaveView(Context context,             @Nullable AttributeSet attrs) {         super(context, attrs);         init();     }     private void init() {         path = new Path();         paint = new Paint();         paint.setColor(Color.RED);         paint.setStyle(Style.STROKE);         paint.setStrokeWidth(10);     }     @Override     protected void onDraw(Canvas canvas) {         super.onDraw(canvas);         //第一个点--起始点         path.moveTo(100, 400);         //二阶贝塞尔曲线1         path.quadTo(250, 200, 400, 400);         //二阶贝塞尔曲线2(后面的曲线的起始点默认是接着上一个曲线的结束点)         path.quadTo(550, 600, 700, 400);         //关闭路径(将起点和终点闭合)         path.close();         canvas.drawPath(path, paint);     } } 复制代码

     Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第16张  ##### 三阶贝塞尔曲线

**

        path.moveTo(100, 700);         path.cubicTo(50, 500, 550, 500, 700, 700);         canvas.drawPath(path, paint); 复制代码

     Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第17张  

波浪实例

public class WaveView extends View {     private Paint paint;     private Path path;     //波长     private int waveLength = 800;     private int dx;     private int dy;     public WaveView(Context context) {         super(context);     }     public WaveView(Context context,             @Nullable AttributeSet attrs) {         super(context, attrs);         init();     }     private void init() {         path = new Path();         paint = new Paint();         paint.setColor(Color.RED);         paint.setStyle(Style.FILL_AND_STROKE);         paint.setStrokeWidth(10);     }     @Override     protected void onDraw(Canvas canvas) {         super.onDraw(canvas);         path.reset();         int originY = 500; //        if(dy<originY + 150){ //            dy += 30; //        }         int halfWaveLength = waveLength / 2;         path.moveTo(-waveLength + dx, originY - dy);         //屏幕宽度里面画多少哥波长         for (int i = -waveLength; i < getWidth() + waveLength; i += waveLength) {             //二阶贝塞尔曲线1             /**              * 相对于起始点的增量              */             path.rQuadTo(halfWaveLength / 2, -150, halfWaveLength, 0);             path.rQuadTo(halfWaveLength / 2, 150, halfWaveLength, 0);         }         //颜色填充         //画一个封闭的空间         path.lineTo(getWidth(), getHeight());         path.lineTo(0, getHeight());         path.close();         canvas.drawPath(path, paint);     }     public void startAnimation() {         ValueAnimator animator = ValueAnimator.ofInt(0, waveLength);         animator.setDuration(1000);         animator.setInterpolator(new LinearInterpolator());         //无限循环         animator.setRepeatCount(ValueAnimator.INFINITE);         animator.addUpdateListener(new AnimatorUpdateListener() {             @Override             public void onAnimationUpdate(ValueAnimator animation) {                 dx = (int) animation.getAnimatedValue();                 postInvalidate();             }         });         animator.start();     } } 复制代码

调用

WaveView waveView = findViewById(R.id.waveView); waveView.startAnimation(); 复制代码

     Android 高级UI10 Path及其贝塞尔曲线 android贝塞尔曲线 贝塞尔曲线 第18张
作者:冬日毛毛雨
链接:https://juejin.cn/post/7012877334134915080


Tag:android贝塞尔曲线 贝塞尔曲线
相关文章

发表评论: