贝塞尔曲线

为何要讲贝塞尔曲线,实际上 Android 中不少效果都有用到贝塞尔曲线。html

QQ 的消息拽拖小红点旗袍消失的效果java

QQ空间 直播页面右下角的礼物冒泡特效 android

水流波动效果git

图片或书本翻页效果github

一个弹性效果的抽屉菜单算法


能够先对贝塞尔曲线有一个大概的认识。canvas

贝塞尔曲线维基百科api

历史


贝塞尔曲线的数学基础是早在 1912 年就广为人知的 伯恩斯坦多项式 。但直到 1959 年,当时就任于雪铁龙的法国数学家 Paul de Casteljau 才开始对它进行图形化应用的尝试,并提出了一种数值稳定的 de Casteljau 算法。然而贝塞尔曲线的得名,倒是因为 1962 年另外一位就任于雷诺的法国工程师 Pierre Bézier 的普遍宣传。他使用这种只须要不多的控制点就可以生成复杂平滑曲线的方法,来辅助汽车车体的工业设计。函数

正是由于控制简便却具备极强的描述能力,贝塞尔曲线在工业设计领域迅速获得了普遍的应用。不只如此,在计算机图形学领域,尤为是矢量图形学,贝塞尔曲线也占有重要的地位。今天咱们最多见的一些矢量绘图软件,如 Flash、Illustrator、CorelDraw 等,无一例外都提供了绘制贝塞尔曲线的功能。甚至像 Photoshop 这样的位图编辑软件,也把贝塞尔曲线做为仅有的矢量绘制工具(钢笔工具)包含其中。工具

贝塞尔曲线在 Web 开发领域一样占有一席之地。CSS3 新增了 transition-timing-function 属性,它的取值就能够设置为一个三次贝塞尔曲线方程。在此以前,也有很多 JavaScript 动画库使用贝塞尔曲线来实现美观逼真的缓动效果。


公式

线性贝塞尔曲线

给定点P0、P1,线性贝塞尔曲线只是一条两点之间的直线。这条线由下式给出:

二次方贝塞尔曲线

二次方贝塞尔曲线的路径由给定点P0、P一、P2的函数B(t)追踪:

三次方贝塞尔曲线

P0、P一、P二、P3 四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于 P0 走向 P1 ,并从 P2 的方向来到 P3 。通常不会通过 P1 或 P2 ;这两个点只是在那里提供方向资讯。 P0 和 P1 之间的间距,决定了曲线在转而趋进 P2 以前,走向 P1 方向的“长度有多长”。

曲线的参数形式为:

n阶贝塞尔曲线

n阶贝塞尔曲线可以下判断,给定点P0、p一、...、Pn,其贝塞尔曲线即


看公式仍是有些抽象,接下来能够看一下图解,具像的了解一下什么是贝塞尔曲线:以二阶贝塞尔曲线和三阶贝塞尔曲线为例。

有一篇文章写的极好

贝塞尔曲线扫盲

贝塞尔曲线不只能画直线,也能画曲线。即使是更复杂的曲线,控制点的增长也只是线性的。这一特色使其不光在工业设计领域大展拳脚,就连数学基础很差的人也能够比较容易地掌握,好比大多数平面美术设计师们。

简单来讲,贝塞尔曲线就是将任意一条曲线转化为准确的数学公式。 Bezier 曲线是用一系列点来控制曲线状态的。


一些关键的名词

  • 数据点:一般是指一条路径的起始点和终止点
  • 控制点:控制点决定了一条路径的弯曲轨迹,根据控制点的个数,贝塞尔曲线被分为一阶贝塞尔曲线(0个控制点)、二阶贝塞尔曲线(1个控制点)、三阶贝塞尔曲线(2个控制点),以此类推。

在Android中的应用

Android 开发中,咱们只考虑二阶贝塞尔曲线和三阶贝塞尔曲线, SDK 也是只提供了二阶和三阶的 API 调用。

固然,对于再高阶的贝塞尔曲线,一般能够拆分红多个低阶的贝塞尔曲线。

推荐一个好的贝塞尔曲线的动态演示,能够很直观的感觉一下:

myst729.github.io/bezier-curv…

这里推荐 医生 的一片博文,已经很是全面的介绍了贝塞尔曲线在 Android 中的一些用法及实例,写的很好。

贝塞尔曲线开发的艺术

下面的内容都基于这篇文章。

二阶贝塞尔曲线在 Android 中的 API 为:

quadTo 是基于绝对坐标,而 rQuadTo 是基于相对坐标。

mPath.moveTo(mStartPointX, mStartPointY);
//二阶贝塞尔曲线
mPath.quadTo(mAuxiliaryX, mAuxiliaryY, mEndPointX, mEndPointY);
canvas.drawPath(mPath, mPaintBezier);复制代码

三阶贝塞尔曲线在 Android 中的 API 为:

这两个API在原理上也是能够互相转换的。

两个点的话涉及到多点触摸,有兴趣能够看看下面这篇文章。

Android MotionEvent详解

cubicTo是基于绝对坐标,而rCubicTo是基于相对坐标。

mPath.moveTo(mStartPointX, mStartPointY);
// 三阶贝塞尔曲线
mPath.cubicTo(mAuxiliaryOneX, mAuxiliaryOneY, mAuxiliaryTwoX, mAuxiliaryTwoY, mEndPointX, mEndPointY);
canvas.drawPath(mPath, mPaintBezier);复制代码

三阶贝塞尔曲线其实也没什么,就是多了一个控制点,记录下他的位置就能够了。

圆滑绘图

当在屏幕上绘制路径的时候,咱们一般会经过 Path.lineTo 将各个触点链接起来,可是这样确定会很生硬。由于是经过直线来链接的。若是经过二阶贝塞尔曲线,就会圆滑不少。不会出现太多的生硬链接。

if (dx >= offset || dy >= offset) {
                    // 贝塞尔曲线的控制点为起点和终点的中点
                    float cX = (x1 + preX) / 2;
                    float cY = (y1 + preY) / 2;
                    mPath.quadTo(preX, preY, cX, cY);
// mPath.lineTo(x1, y1);
                    mX = x1;
                    mY = y1;
                }复制代码

经过纪录 Move 过程当中点位置的变化,而后传入 quadTo 中的参数,就能够实现圆滑的绘图。

根据公式咱们能够模仿着写一个工具类:

public class BezierUtil {

    /** * B(t) = (1 - t)^2 * P0 + 2t * (1 - t) * P1 + t^2 * P2, t ∈ [0,1] * * @param t 曲线长度比例 * @param p0 起始点 * @param p1 控制点 * @param p2 终止点 * @return t对应的点 */
    public static PointF CalculateBezierPointForQuadratic(float t, PointF p0, PointF p1, PointF p2) {
        PointF point = new PointF();
        float temp = 1 - t;
        point.x = temp * temp * p0.x + 2 * t * temp * p1.x + t * t * p2.x;
        point.y = temp * temp * p0.y + 2 * t * temp * p1.y + t * t * p2.y;
        return point;
    }

    /** * B(t) = P0 * (1-t)^3 + 3 * P1 * t * (1-t)^2 + 3 * P2 * t^2 * (1-t) + P3 * t^3, t ∈ [0,1] * * @param t 曲线长度比例 * @param p0 起始点 * @param p1 控制点1 * @param p2 控制点2 * @param p3 终止点 * @return t对应的点 */
    public static PointF CalculateBezierPointForCubic(float t, PointF p0, PointF p1, PointF p2, PointF p3) {
        PointF pointF = new PointF();
        float temp = 1- t;
        pointF.x = p0.x * temp * temp * temp + 3 * p1.x * t * temp * temp + 3 * p2.x * t * t * temp + p3.x * t * t * t;
        pointF.y = p0.y * temp * temp * temp + 3 * p1.y * t * temp * temp + 3 * p2.y * t * t * temp + p3.y * t * t * t;
        return pointF;
    }


}复制代码

推荐一个关于贝塞尔曲线的开源项目:

github.com/venshine/Be… ( 经过 de Casteljau 算法绘制贝塞尔曲线,并计算它的切线,实现 1-7 阶贝塞尔曲线的造成动画 )

参考博客:

Android 绘制 N 阶 Bezier 曲线

相关文章
相关标签/搜索