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 可以通过回调函数判断动画 ...
随机推荐
- please get a license from www.texturepacker.com
我们在使用texturepacker创建资源后,在使用资源时出现下述问题:please get a license from www.texturepacker.com 如图: 这个是由于我们的版本号 ...
- 仅仅需一步教你解决Win10下Android Studio terminal无法使用的问题
Android Studio集成和加入了一些有用的工具.当中一个便是terminal. 在Windows平台下Android Studio中的terminal在原理上实际使用的是window中的cmd ...
- FreeRTOS系列第14篇---FreeRTOS任务通知
注:本文介绍任务通知的基础知识,具体源代码分析见<FreeRTOS高级篇8---FreeRTOS任务通知分析> 每一个RTOS任务都有一个32位的通知值,任务创建时,这个值被初始化为0.R ...
- ios之UILabel实现文本自适应方法
UILabel实现文本自适应方法(ios7) - (void)initUserInterface { UILabel *label = [[UILabel alloc]init]; label.num ...
- Dijkstra算法——最短路径(转)
转自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html Dijkstra算法 1.定义概览 Dijkstra(迪杰斯 ...
- JVM架构
1 JVM的内存模型 1.1 堆空间 每个jvm都有一个堆,所有的对象都放在这里. 1.2 java栈空间 每个线程都有一个java栈,所有的java栈都放在这里. 1.3 本地方法栈 每个线程都有一 ...
- mystr = '{}{}{}'.format(mystr, random.randint(0, 9), adurl)
mystr = '{}{}{}'.format(mystr, random.randint(0, 9), adurl)
- canvas绘图数学知识总结
题外话: 最近看了一本书叫 <HTML5 Canvas核心技术 图形.动画与游戏开发>已经算是看了85%,基本接近尾声,所以近期会多总结一些关于canvas的东西, 这本书讲的还算可以,最 ...
- android 6.0编译时出现ERROR:Security problem ,see jack server log【转】
本文转载自:http://blog.csdn.net/a567890k/article/details/52956798 最近编译Android6.0时经常出现以下错误 临时解决方法: Buildin ...
- input keyevent发送按键值【转】
本文转载自:http://blog.csdn.net/moyu123456789/article/details/71209893 1.adb shell进入android设备,执行命令input k ...