php中文网数学符号的显示太差了,推荐看这里

贝塞尔曲线简介:
贝塞尔曲线,是贝塞尔老爷子在使用电子计算机设计汽车零件的时候 进行曲面设计而采用的一种参数化的样条曲线.

一般参数方程:

B(t) = \sum_{i=0}^nC_n^iP_i(1-t)^{n-i}t^i

由公式很容易可以看出n阶贝塞尔曲线需要的点数是n+1个点,该公式为参数方程,并不是一般意义上的y=f(x),而是y = f(t),x = f(t).

贝塞尔曲线就是用来画曲线的,以三阶贝塞尔曲线为例,他有四个控制点,第一个点和最后一个点是这条曲线的起始点和终止点,曲线必定会经过这两个点,而第二个和第三个则是控制曲线形状的,更直接来说通过改变第二个点和第三个 点的位置,曲线的斜率就会受到影响。具体的影响可以直接打开chrome调试面板任意设置一个transition属性 然后观察其timing-function 看到效果。

上边说到了斜率,那其实在一个位移-时间的曲线方程中,斜率则代表了速度,实际在web动画中位移可以换成任何一个属性(详见早年间关于动画的一些论断)

那其实用js实现一条三阶贝塞尔曲线,无外呼是找一个 时间x -> 其他任意属性y 之间的映射。

这里,x我们是已知的,现在的需求就是解出y,以CSS的transition-timing-function做为一个参考,我们可以把起始点和终止点的坐标设置成(0,0)和(1,1) (实际很多东西都会这么处理,最后的结果做一个线性映射就好),自然两个控制点的范围也应该在0-1之间。

先将贝塞尔曲线展开成一般形式:

B(t) = P_0(1-t)^3 + 3P_1t(1-t)^2 + 3P2t^2(1-t) + P3t^3

起始、终止点带入简化:

B(t) = 3P_1t(1-t)^2 + 3P_2t^2(1-t) + t^3

OK,理论完成可以实践了。

假定,我们得到某一时刻的时刻值 x , 那么通过参数方程B(t) = x , 可求得参数t的值,再将该t带入 y = B (t),中即可求得我们想要的最终结果y。

所以,归根结底,第一件事情是要解方程,多次函数的求根并不容易,这里具体实现的时候,我们可以参考chromium的贝塞尔曲线实现,来解决这个问题,具体的做法是,首先通过8次牛顿迭代,如果找到了就直接return结果,如果没有,就开始Bisection_method(应该叫对分法)

牛顿迭代的原理,简而言之就是在一条曲线上任选一点做切线,然后在该切线与x轴的交点上做一条垂直于x轴的直线,假设该直线与曲线相交于另一个点,再在该点做切线。。。 一直重复此过程,切线于x轴的交点会越来越与曲线的根接近。

基本推导:
假设有曲线y = f(x) 该曲线上任取一点x_0,y_0,做该点切线,
则,该点处切线的斜率为f^{(1)}(x_0);
由曲线方程 y = kx + b 代入以上参数得
b = f(x_0) - f^{(1)}(x_0)x_0
故 切线方程为 g(x) = f(x_0) - f^{(1)}(x_0)(x_0-x);
得到该切线与x轴得交点为x_1 = x_0 - \frac{f(x_0)}{f^{(1)}(x_0)}
这便是一次迭代。x1便是我们得到第一个近似根,在往后得迭代中,假如这个近似跟与实际根的误差在一个我们可接受的范围内,便可以将这个根当作真根。

Bisection_method的基本推导则是假如连续函数y = f(x) 在区间[a,b]上连续,且f(a)与f(b)符号相反,那么函数y在区间[a,b]上至少有一个根。然后二分这个区间进行求值。

代码:

  1. type coordinate = {
  2. x: number,
  3. y: number
  4. }
  5. export class cubicBezier{
  6. p1: coordinate
  7. p2: coordinate
  8. precision = 1e-5;
  9. constructor(x1,y1,x2,y2){
  10. this.p1 = {
  11. x:x1,
  12. y:y1
  13. };
  14. this.p2 = {
  15. x:x2,
  16. y:y2
  17. };
  18. }
  19. getX(t:number){
  20. let x1 = this.p1.x,x2=this.p2.x;
  21. return 3*x1*t*Math.pow(1-t,2) + 3* x2*Math.pow(t,2) * (1-t) + Math.pow(t,3)
  22. }
  23. getY(t:number){
  24. let y1 = this.p1.y,y2=this.p2.y;
  25. return 3*y1*t*Math.pow(1-t,2) + 3*y2*Math.pow(t,2) * (1-t) + Math.pow(t,3)
  26. }
  27. // https://github.com/amfe/amfe-cubicbezier/blob/master/src/index.js
  28. solveCurveX(x:number){
  29. var t2 = x;
  30. var derivative;
  31. var x2;
  32. var p1x = this.p1.x, p2x = this.p2.x;
  33. var ax = 3 * p1x - 3 * p2x + 1;
  34. var bx = 3 * p2x - 6 * p1x;;
  35. var cx = 3 * p1x;;
  36. function sampleCurveDerivativeX(t:number){
  37. // `ax t^3 + bx t^2 + cx t' expanded using Horner 's rule.
  38. return (3 * ax * t + 2 * bx) * t + cx;
  39. }
  40. // https://trac.webkit.org/browser/trunk/Source/WebCore/platform/animation
  41. // First try a few iterations of Newton's method -- normally very fast.
  42. // http://en.wikipedia.org/wiki/Newton's_method
  43. for (let i = 0; i < 8; i++) {
  44. // f(t)-x=0
  45. x2 = this.getX(t2) - x;
  46. if (Math.abs(x2) < this.precision) {
  47. return t2;
  48. }
  49. derivative = sampleCurveDerivativeX(t2);
  50. // == 0, failure
  51. if (Math.abs(derivative) < this.precision) {
  52. break;
  53. }
  54. // xn = x(n-1) - f(xn)/ f'(xn)
  55. // 假设g(x) = f(t) - x
  56. // g'(x) = f'(t)
  57. //所以 f'(t) == g'(t)
  58. // derivative == g'(t)
  59. t2 -= x2 / derivative;
  60. }
  61. // Fall back to the bisection method for reliability.
  62. // bisection
  63. // http://en.wikipedia.org/wiki/Bisection_method
  64. var t1 = 1;
  65. var t0 = 0;
  66. t2 = x;
  67. while (t1 > t0) {
  68. x2 = this.getX(t2) - x;
  69. if (Math.abs(x2) < this.precision) {
  70. return t2;
  71. }
  72. if (x2 > 0) {
  73. t1 = t2;
  74. } else {
  75. t0 = t2;
  76. }
  77. t2 = (t1 + t0) / 2;
  78. }
  79. // Failure
  80. return t2;
  81. }
  82. solve(x:number){
  83. return this.getY( this.solveCurveX(x) )
  84. }
  85. }

3阶(次)贝塞尔曲线的JavaScript(JS)实现的更多相关文章

  1. 贝塞尔曲线算法,js贝塞尔曲线路径点

    //anchorpoints:贝塞尔基点 //pointsAmount:生成的点数 //return 路径点的Array function CreateBezierPoints(anchorpoint ...

  2. 【Unity3d游戏开发】游戏中的贝塞尔曲线以及其在Unity中的实现

    RT,马三最近在参与一款足球游戏的开发,其中涉及到足球的各种运动轨迹和路径,比如射门的轨迹,高吊球,香蕉球的轨迹.最早的版本中马三是使用物理引擎加力的方式实现的足球各种运动,后来的版本中使用了根据物理 ...

  3. 贝塞尔曲线(B-spline)的原理与应用

    什么是贝塞尔曲线? 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线. 来源 贝塞尔曲线于1962,由法国工程师皮埃尔·贝塞尔(Pierre Béz ...

  4. JS模拟CSS3动画-贝塞尔曲线

    一.什么是贝塞尔曲线 1962年,法国工程师皮埃尔·贝塞尔(Pierre Bézier),贝塞尔曲线来为为解决汽车的主体的设计问题而发明了贝塞尔曲线.如今,贝赛尔曲线是计算机图形学中相当重要的一种曲线 ...

  5. JavaScript+canvas 利用贝塞尔曲线绘制曲线

    效果图: <body> <canvas id="test" width="800" height="300">< ...

  6. [js高手之路] html5 canvas系列教程 - arcTo(弧度与二次,三次贝塞尔曲线以及在线工具)

    之前,我写了一个arc函数的用法:[js高手之路] html5 canvas系列教程 - arc绘制曲线图形(曲线,弧线,圆形). arcTo: cxt.arcTo( cx, cy, x2, y2, ...

  7. 贝塞尔曲线 WPF MVVM N阶实现 公式详解+源代码下载

    源代码下载 效果图: 本程序主要实现: N阶贝塞尔曲线(通用公式) 本程序主要使用技术 MVVM InterAction 事件绑定 动态添加Canvas的Item 第一部分公式: n=有效坐标点数量 ...

  8. n阶贝塞尔曲线绘制(C/C#)

    原文:n阶贝塞尔曲线绘制(C/C#) 贝塞尔是很经典的东西,轮子应该有很多的.求n阶贝塞尔曲线用到了 德卡斯特里奥算法(De Casteljau's Algorithm) 需要拷贝代码请直接使用本文最 ...

  9. 深度掌握SVG路径path的贝塞尔曲线指令

    一.数字.公式.函数.变量,哦,NO! 又又一次说起贝塞尔曲线(英语:Bézier curve,维基百科详尽中文释义戳这里),我最近在尝试实现复杂的矢量图形动画,发现对贝塞尔曲线的理解馒头那么厚,是完 ...

  10. canvas绘制二次贝塞尔曲线----演示二次贝塞尔四个参数的作用

    canvas中绘制二次贝塞尔曲线的方法为ctx.quadraticCurveTo(x1,y1,x2,y2); 四个参数分别为两个控制点的坐标.开始点即当前canvas中目前的点,如果想从指定的点开始, ...

随机推荐

  1. bash 和 zsh 中while循环的方式

    bash: while true; do ./a.out; done zsh: while true; do ./a.out;

  2. Redis Stream类型的使用详解

    目录 一.背景 二.redis中Stream类型的特点 三.Stream的结构 四.Stream的命令 1.XADD 往Stream末尾添加消息 1.命令格式 2.举例 2.XRANGE查看Strea ...

  3. containerd.service containerd-1.6.8-linux-amd64.tar.gz cni-plugins-linux-amd64-v1.1.1.tgz 标准文件下载

    配置K8S时 可能会用到#systemcd来管理containerd,这https://raw.githubusercontent.com/containerd/containerd/main/con ...

  4. CSS:盒子_每个元素都有两个盒子(《CSS世界》笔记-块级元素)

    CSS:盒子_每个元素都有两个盒子(<CSS世界笔记>-块级元素) 1)CSS世界只有"块级盒子(block-level box)"和"内联盒子(inline ...

  5. 数据类型之字符串(string)(四)

    字符串本质是:字符序列不可变1.字符串编码,Unicode ord('A') ord('王') 2.创建字符串,引号 a = 'Hello python!' b = "I'm a teach ...

  6. golang 切片(slice)

    1.切片的定义 切片(slice)是对数组一个连续片段的引用,所以切片是一个引用类型. 切片的使用与数组类似,遍历,访问切片元素等都一样.切片是长度是可以变化的,因此切片可以看做是一个动态数组. 一个 ...

  7. 【SQL Server】按日期分组产品

    1 SELECT sell_date ,COUNT(1) AS num_sold, 2 STUFF(( 3 SELECT ',' + son.product 4 FROM (SELECT DISTIN ...

  8. D. Triangle Coloring

    https://codeforces.com/contest/1795/problem/D #include <iostream> #include <cstring> #in ...

  9. GPS北斗卫星时钟同步系统提升电信支撑网性能

    GPS北斗卫星时钟同步系统提升电信支撑网性能 京准科技提供参考--更多资料VX(ahjzsz) 各项新的数据业务,如电子商务.多媒体通信.IP电话等都是电信业务发展的新增长点,而传统业务也存在多家企业 ...

  10. win10系统每次重启桌面图标排列都会改动怎么办

    鼠标右键点击个性化>主题>找到桌面图标设置>把计算机 回收站 用户的文件 控制面板 网络等前面框复选框全部勾选掉,然后在桌面新建文件夹把桌面所有的图标剪切到新建文件里面,然后把新建文 ...