JS模拟CSS3动画-贝塞尔曲线
一、什么是贝塞尔曲线
1962年,法国工程师皮埃尔·贝塞尔(Pierre Bézier),贝塞尔曲线来为为解决汽车的主体的设计问题而发明了贝塞尔曲线。如今,贝赛尔曲线是计算机图形学中相当重要的一种曲线,它能过优雅地模拟人手绘画出的线。它通过控制曲线上的点(起始点、终止点以及多个参考点)来创造、编辑图形。其中起重要作用的是位于曲线中央的控制线。这条线是虚拟的,中间与贝塞尔曲线交叉,两端是控制端点。移动两端的端点时贝塞尔曲线改变曲线的曲率(弯曲的程度);移动中间点(也就是移动虚拟的控制线)时,贝塞尔曲线在起始点和终止点锁定的情况下做均匀移动。
二、贝塞尔曲线的应用
贝赛尔曲线广泛应用于绘图软件中,例如Adobe PhotoShop、Adobe Flash。
Android可以通过自定义的view来实现贝塞尔曲线
ios则可以使用UIBezierPath类来生成贝塞尔曲线
前端,canvas bezierCurveTo,css animation-timing-function: cubic-bezier(x,x,x,x}都有关于贝赛尔曲线的一些应用
三、贝塞尔曲线公式及其分析
一次:
二次:
三次:
n次
但是公式中只是给出了点与点之间的关系,并没有给出y与x坐标的关系,为此我们需要对其进行分解,下面以三次贝塞尔曲线为例子:
四、贝塞尔曲线在动画中的应用
如图,X轴用来表示时间,Y轴用来表示动画的完成度。所以贝塞尔曲线在动画中的应用很简单,每隔一定时间传入当前动画的执行时间占总时间的比例然后就可以得出动画在此时刻完成的程度,最后只需要设置一下此时刻动画的完成度就行了。由于它的起始坐标分别为(0,0),(1,1)。
JS代码实现
我们已经求出了三次贝塞尔曲线x,y与t的关系,那么就可以根据这个关系通过JS实现
function UnitBezier(p1x,p1y,p2x,p2y) {
this.cx = 3.0 * p1x;
this.bx = 3.0 * (p2x - p1x) - this.cx;
this.ax = 1.0 - this.cx -this.bx;
this.cy = 3.0 * p1y;
this.by = 3.0 * (p2y - p1y) - this.cy;
this.ay = 1.0 - this.cy - this.by;
}
UnitBezier.prototype = {
sampleCurveX : function(t) {
return ((this.ax * t + this.bx) * t + this.cx) * t;
},
sampleCurveY : function(t) {
return ((this.ay * t + this.by) * t + this.cy) * t;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
可能到这里感觉上,我们已经实现了贝塞尔曲线的在动画上的应用了,我们看下这个demo.
然而我们发现原始JS实现的动画效果明显不同于CSS3中的动画效果。那么该如何去模拟了?看下面的代码:
function UnitBezier(p1x,p1y,p2x,p2y) {
this.cx = 3.0 * p1x;
this.bx = 3.0 * (p2x - p1x) - this.cx;
this.ax = 1.0 - this.cx -this.bx;
this.cy = 3.0 * p1y;
this.by = 3.0 * (p2y - p1y) - this.cy;
this.ay = 1.0 - this.cy - this.by;
}
UnitBezier.prototype = {
sampleCurveX : function(t) { //贝赛尔曲线t时刻的坐标点的X坐标
return ((this.ax * t + this.bx) * t + this.cx) * t;
},
sampleCurveY : function(t) { //贝赛尔曲线t时刻的坐标点的y坐标
return ((this.ay * t + this.by) * t + this.cy) * t;
},
solve:function(t){
this.sampleCurveY(this.sampleCurveX(t))
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
我们再来测试一下看下效果
额,这下差别更大。但是仔细想想这里所有的数据基本都是浮点运算,那么产生的误差可想而知。
五、浮点型运算误差
在计算机中浮点型运算造成的误差非常普遍,不管是C、C++、java、javaScript等待语言都存在,因为都是按照IEEE 754标准来进行浮点运算。
IEEE 754
按照IEEE 754 标准,32位中有:
- 1位是符号位(sign)
- 8位是指数位(exponent)
- 23位是数值 (fraction)
那么计算出的结果为:
举些栗子
比如 0.1的单精度浮点数在计算机二进制数为:
0 01111011 10011001100110011001101
那么实际值为
比如 0.5的单精度浮点数在计算机二进制数为:
0 01111110 00000000000000000000000
六、怎样缩小浮点型运算产生的误差
首先我们可以来看下最简单的减少误差的方法
放大法
由于浮点型运算会产生误差,因此我们可以变相地将它放大,知道它为整数,最后返回的时候在将值还原,而这种方法是为完全将误差消除的。
Math.formatFloat = function(f, digit) {
var m = Math.pow(10, digit);
return parseInt(f*m,10) m;
}
var numA = 0.1;
var numB = 0.2;
alert(Math.formatFloat(numA+numB,1)===0.3);
虽然这种方法在JS中能够很好地消除误差,但是并不是所有的场景均适应。它比较时候简单的加减运算和位数较低的乘法除法运算,这是因为在JS中精确整数的范围被定义为:−9007199254740992到9007199254740992(2的53次方),也就是说最多16位。然而我们的贝塞尔曲线应用在动画的过程中肯定会产生位数超过16位的浮点数,这种方式仍然不能解决问题。
二分法
二分法是我们在高中的时候老师就已经给我们讲过,不过那个时候通常是用来判断f(x0)是正数还是负数,有时候还会给出精度要求。在这里我们同样也可以使用二分法来解决,我们只需要不断地利用二分法找出(f(x0)-x)
function division(x,t1,t2, epsilon,func) {//计算x的近似值
var t0,
t1,
t2,
x2,
i;
t2 = x;
if (t2 < t0)
return t0;
if (t2 > t1)
return t1;
while (t0 < t1) {
x2 = func(t2);
if (Math.abs(x2 - x) < epsilon)
return t2;
if (x > x2)
t0 = t2;
else t1 = t2;
t2 = (t1 - t0) * .5 + t0;
}
return t2;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
牛顿迭代法
牛顿迭代法也是常常在计算机中减少误差的一种常用方法,公式如下:
设r是f(x)=0的根,选取x0作为r的初始近似值,过点(x0,f(x0))做曲线 的切线L,L的方程为y=f(x0)+f’(x0)(x-x0),求出L与x轴交点的横坐标 x1=x0-f(x0)/f’(x0) ,称x1为r的一次近似值。过点 做曲线 的切线,并求该切线与x轴交点的横坐标 ,称 为r的二次近似值。重复以上过程,得r的近似值序列,其中,xn+1=xn-f(xn)/f’(xn)称为r的n+1次近似值。
在处理贝塞尔曲线的过程中,由于我们不可能求出真正准确的值,为此我们只需要满足f(x0)-x
最终的效果
最后已经非常接近CSS3自带的贝塞尔曲线动画效果了,虽然仍有一点差别,这是因为采取的方法只能使误差只能缩小而不能被消除,而且精度越多,那么JS动画性能就越差,所以这里精度为设定为0.01.
原文见这里(http://www.yuchenblog.cn/?p=102)
JS模拟CSS3动画-贝塞尔曲线的更多相关文章
- css3动画贝塞尔曲线cubic-bezier,css3动画的五种情况
当大家开始做css3动画的时候,了解贝塞尔曲线就成了不可或缺的.“贝赛尔曲线”是由法国数学家Pierre Bézier所发明,由此为计算机矢量图形学奠定了基础.它的主要意义在于无论是直线或曲线都能在数 ...
- js 模拟css3 动画3
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- js 模拟css3 动画1
<html> <head> <title> javaScript缓动入门 </title> </head> <body> < ...
- js 模拟css3 动画
<html> <head> <title> javaScript缓动入门 </title> </head> <body> < ...
- css3 动画贝塞尔曲线
http://cubic-bezier.com/#.17,.67,.83,.67 缓动函数速查表: http://www.xuanfengge.com/easeing/easeing/ Ceaser: ...
- js 模拟css3 动画2
<html> <head> <title> javaScript缓动入门 </title> </head> <body> < ...
- 如何使用js捕获css3动画
如何使用js捕获css3动画 css3动画功能强大,但是不像js,没有逐帧控制,但是可以通过js事件来确定任何动画的状态. 下面是一段css3动画代码: #anim.enable{ -webkit-a ...
- wow.js让css3动画变动更有趣(滚动页面动画模拟懒加载特效)
CSS3的出现给网站页面增加了活力,网站增色不少,有这么小小的一款插件就能做出很多动画效果. 最重要的是它:简单易用.轻量级.无需 jQuery......他就是wow.js 地址:https://d ...
- 原生js判断css3动画过度(transition)结束 transitionend事件 以及关键帧keyframes动画结束(animation)回调函数 animationEnd 以及 css 过渡 transition无效
上图的 demo 主要讲的 是 css transition的过渡回调函数transitionend事件: css3 的时代,css3--动画 一切皆有可能: 传统的js 可以通过回调函数判断动画 ...
随机推荐
- STM8S---外部中断应用之长按键识别
STM8经常使用中断指令 开总中断 _asm("rim"); 禁止中断 _asm("sim"); 进入停机模式 _asm("halt"); ...
- SQL语句小结
1.创建数据库 create database 数据库名 2.删除数据库 drop database 数据库名 3.创建表 1>.create table 表名 (col1 type1 [no ...
- FunctionGraph无缝集成Express应用
Express APP 作为一个Node.js开发者,相信大家都可能会使用Express框架,无论是构建后端服务,或是搭建一个前端的开发态服务器,Express都是一个很流行的选择.构建Express ...
- css3 3d特效汇总
本篇全是实战,没有基础,如果不明白3d特效的原理,可能会看不懂,不过没关系,给你推荐一下 张鑫旭css3 3d转换,或者看我的另一篇博客 css3 2d转换3d转换以及动画的知识点汇总,看完这些3d ...
- clojure学习记录
take 从列表中获取子列表 into a b 把b conj 到a中 (defn count-a-seq [lat] (reduce (fn [x y] (+ x 1)) 0 lat)) red ...
- easyui图标对照
转自:https://blog.csdn.net/qq_34545192/article/details/78250816 原作者文章地址: http://www.cnblogs.com/timeme ...
- 昆石VOS3000_2.1.2.0完整安装包及安装脚本
安装包下载地址 http://www.51voip.org/post/57.html 安装教程: 上传安装包 ·给整个目录授权 chmod 777 /root/vosintsall 1.安装前准备 首 ...
- Ubuntu下 VirtualBox的卸载和升级 (转载)
转载:http://blog.csdn.net/li_hai/article/details/8164744 首先,在终端查看已经安装的VirtualBox的版本: $ dpkg -l 查看到版本号, ...
- E2017E0605-hm
carbon copy 抄送, 抄写与送达 blind carbon copy 密送 blind adj. 失明的; 盲目的,轻率的; contact n. 接触; 触点 v 联系,接触; ...
- 【Learning】多项式的一些东西
FFT 坑 NTT 将\(FFT\)中的单位复数根改成原根即可. 卡常版NTT模版 struct Mul { int Len; int wn[N], Lim; int rev[N]; inline v ...