JavaScript动画知多少?
今天,小学生以自己浅薄的见地,在前辈大能的基础上写这篇文章,希望给大家打开一扇窥探JavaScript(以下简称JS)动画的窗户。
JS如何制造出动画效果?
结合浏览器提供的 setInterval 或 setTimeout API,高频改变DOM元素的一些属性,即可创造一个肉眼可见的动画效果。一个看起来非常流畅的JS动画除了需要良好的变换算法外,与其执行宿主也是非不开的。程序写得再好,如果浏览器过于老旧,电脑CPU性能低下,也会出现卡顿,甚至卡死。
执行一个动画函数对于浏览器来说是个苦差,设置动画一帧为多长时间才能既流畅又不损耗性能呢?浏览器不会傻到进行一个DOM操作,就去渲染一次页面。它会把一个周期内所有的DOM操作整合起来,统一进行一次渲染。这个周期大约在16.7ms左右,不同浏览器间会有几毫秒的差异。SetTimeout的第二个参数设置为1000/60是比较合乎情理的做法。不过了解过SetTimeout运行机制的都会清楚,这个时间并不可靠,其根据实际情况会有些许甚至相当大的延迟。那么有没有这样一个API?我不想知道你浏览器到底多久渲染一次,反正你渲染的时候给我的动画执行一帧就行了。答案是有,requestAnimationFrame,可以让函数随着浏览器渲染执行,并且执行时机是可靠的。注意,这个方法在现在浏览器及IE10+才被支持。
现在可以封装起一个简单的requestAnimationFrame,下面的例子中将会使用到它。
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
更加详细的封装可以在张鑫旭的博客中看到:张鑫旭:requestAnimFrame。下面让我们继续。
动画函数的编写
有了requestAnimationFrame,下面该考虑一下如何让写动画函数了。一般来说我们会给出一个毫秒级的during值,限制这个动画必须要在这个时间内完成。下面以实现一个小球从离页面左侧100px处匀速运动到800px处为例,编写一个动画函数:戳我查看DEMO。
var ele = document.getElementById("block");
var start = Date.now();//获取动画开始的时间。
var during = 1000; //此动画要在1秒内执行完。
var p=0;//动画完成度 从0-1;
requestAnimationFrame(function f(){
if(p>=1){ ele.style.left="800px";}//如果发现动画已经执行完,将元素置到终点。
else{
p=(Date.now()-start)/during;
ele.style.left=100+700*p+"px"; //从100px开始,匀速向右移动,共移动700px;
requestAnimationFrame(f);
}
})
上面函数中有一个关键变量:p,即percentage,我们可以称它为动画的完成度,它是根据当前时间计算得出的,并且从动画开始后,会从0~1匀速渐变。当其为1时,表示整个动画执行完毕。在这个函数中,让p乘以要运动的长度700,便会得到一个0-700匀速变化的值,将其加上开始的100,便可模拟小球从100px处匀速移动到800px处。
设想一下,假如上面红色标出的运动方程改为“ele.style.left=100+700*p*p+"px"”呢?p以二次方渐增,小球向右移动的速度会越来越快。是的,稍加修改便可实现一个匀加速运动的小球。
下面,我们就是要针对p来做文章。
Tween算法及缓动效果
下面我将列举一些常用的缓动算法,根据这些算法去修改上面匀速运动函数的运动方程,即可实现很赞的动画效果。
- 2次方缓动: p*p
- 3次方缓动: p*p*p
- 4次方缓动: p*p*p*p
- 5次方缓动: p*p*p*p*p
- 正弦曲线缓动: Math.sin(p*Math.PI/2)
- 指数曲线缓动: Math.pow(2,10*(p-1))
- 圆形曲线缓动: Math.sqrt(1-(p-1)*(p-1))
- 超范围三次方: p*p*(2.70158*p-1.70158)
验证一下吧,比如我现在想实现一个小球向右运动,有一个向左蓄力的动画,我只要把第一个demo的运动方程改为“ele.style.left=100+700*p*p*(2.70158*p-1.70158)+"px"”就行了,看看效果吧:戳我查看DEMO。
其实,每种缓动算法都可以进化为三种缓动方式,分别为ease-in(先慢后快),ease-out(先快后慢),ease-in-out(先慢后快再慢)。
以2次方缓动为例,它本身就是一个匀加速的过程,所以ease-in就是p*p。其ease-out为-(p*(p-2))。关于缓动方式,像阳光一样在他的博客中有更加详细的解释:JavaScript动画、运动算法详细解释与分析。
接下来要放大招了,关于缓动的整合DEMO,戳我吧。
JS动画可以做什么?
除了上面的缓动效果,利用常见的数学公式还可以实现一些周期性运动效果,例如小球匀速圆周运动,小球匀速简谐振动等,如果感兴趣请猛戳DEMO。
那么JS动画可以做什么呢?这就需要发挥我们的个人想象力了,上面的DEMO大部分都在操控单一的属性,比如left,让DOM元素发生位移。事实上在运动方程中,元素的任何style都可以被渐变。试想一下,设置一个DOM元素的opacity从0~1进行2次方缓动,便是一个简单的jQuery fadeOut函数;让一个DOM元素高度从无到有,便是一个简单的jQuery slideDown函数。更加不要忘记的是,在动画过程中不仅仅可以操作一项属性,这为动画带来了无限的可能性,事情变得越来越有趣了:DEMO:一个从小到大变化的球。
再试想一下,使用CSS3属性,例如box-shadow,transform,作出的效果必将会更加绚丽。
总结
上面提到使用CSS3属性,其实如果这个浏览器支持CSS3属性的话,其实可以考虑完全使用CSS3实现一个动画。CSS3自有Animation动画属性,可以简单快捷地实现酷炫的动画效果,并且可以启用GPU加速。美中不足的是仅现代浏览器支持,而JS实现动画胜在可以兼容低版本浏览器。
(作者于2015年6月19号增加)上面将JavaScript动画与CSS3动画的比较并不是特别严谨,更严谨的说法请移步我的博客:实现了一个百度首页的彩蛋——CSS3Animation简介。
动画仅仅是JS操作DOM魅力之冰山一角,而数学与计算机总是能碰撞出耀眼的火花。继续学习JS吧,这是一门神奇的语言,同时也应该了解一些数学知识,往往能够为解决事情带来捷径。
(完)
JavaScript动画知多少?的更多相关文章
- 梅须逊雪三分白,雪却输梅一段香——CSS动画与JavaScript动画
CSS动画并不是绝对比JavaScript动画性能更优越,开源动画库Velocity.js等就展现了强劲的性能. 一.两者的主要区别 先开门见山的说说两者之间的区别. 1)CSS动画: 基于CSS的动 ...
- javascript动画系列第三篇——碰撞检测
前面的话 前面分别介绍了拖拽模拟和磁性吸附,当可视区域内存在多个可拖拽元素,就出现碰撞检测的问题,这也是javascript动画的一个经典问题.本篇将详细介绍碰撞检测 原理介绍 碰撞检测的方法有很多, ...
- javascript动画系列第一篇——模拟拖拽
× 目录 [1]原理介绍 [2]代码实现 [3]代码优化[4]拖拽冲突[5]IE兼容 前面的话 从本文开始,介绍javascript动画系列.javascript本身是具有原生拖放功能的,但是由于兼容 ...
- Javascript动画效果(三)
Javascript动画效果(三) 前面我们已经介绍了速度动画.透明度动画.多物体运动和任意值变化,并且我们在Javascript动画效果(二)中介绍到我们封装了一个简单的插件雏形,接下来我们对前面的 ...
- Javascript动画效果(一)
Javascript动画效果(一) 前面我们介绍了Javascript的回到顶部效果,今天呢,我们对Javascript动画做进一步的研究.在这篇博文中我们只介绍简单的匀速运动.简单的缓冲运动和简单的 ...
- Javascript动画效果(二)
Javascript动画效果(二) 在前面的博客中讲了简单的Javascript动画效果,这篇文章主要介绍我在改变之前代码时发现的一些问题及解决方法. 在前面的多物体宽度变化的例子中,我们给其增加代码 ...
- Javascript动画效果(四)
Javascript动画效果(四) 前面我们自己写了一个小小的关于js动画的插件,下面我们来使用之前的框架来完成我们想要的动画效果.我们经常在淘宝网中看到,鼠标经过某一图片时,该图片有从上滚出而又从下 ...
- 给力的轻量级JavaScript动画框架 - jsMorph
jsMorph 是一个独立的轻量级 JavaScript 动画框架,可以用它来操纵多个 HTML 元素的样式,实现动画效果.此框架会自动检测起始位置.转换单位.调整渲染的速度,以此来获得更流畅的渲染体 ...
- 10 个顶级 JavaScript 动画框架推荐
使用JavaScript可以做出一些引人注目的动画效果,但通常不太容易实现.本文为你整理了10个非常优秀的JavaScript动画框架,使用它们你可以轻松实现动画效果.1. RaphaëlRaphaë ...
随机推荐
- Sublime Text3配置在可交互环境下运行python快捷键
安装插件 在Sublime Text3下面写代码感觉很不错,但是写Python的时候遇到了一些问题. 用Sublime Text3打开python文件,或者在Sublime Text3下写好pytho ...
- Aaron Stannard谈Akka.NET 1.1
Akka.NET 1.1近日发布,带来新特性和性能提升.InfoQ采访了Akka.net维护者Aaron Stannard,了解更多有关Akka.Streams和Akka.Cluster的信息.Aar ...
- javaScript生成二维码(支持中文,生成logo)
资料搜索 选择star最多的两个 第一个就是用的比较多的jquery.qrcode.js(但不支持中文,不能带logo)啦,第二个支持ie6+,支持中文,根据第二个源代码,使得,jquery.qrco ...
- Kotlin与Android SDK 集成(KAD 05)
作者:Antonio Leiva 时间:Dec 19, 2016 原文链接:https://antonioleiva.com/kotlin-integrations-android-sdk/ 使用Ko ...
- TFS 2015 敏捷开发实践 – 在Kanban上运行一个Sprint
前言:在 上一篇 TFS2015敏捷开发实践 中,我们给大家介绍了TFS2015中看板的基本使用和功能,这一篇中我们来看一个具体的场景,如何使用看板来运行一个sprint.Sprint是Scrum对迭 ...
- JQuery阻止事件冒泡
冒泡事件就是点击子节点,会向上触发父节点,祖先节点的点击事件. 我们在平时的开发过程中,肯定会遇到在一个div(这个div可以是元素)包裹一个div的情况,但是呢,在这两个div上都添加了事件,如果点 ...
- SQL数据类型
1.Character 字符串: 数据类型 描述 存储 char(n) 固定长度的字符串.最多8,000个字符. n varchar(n) 可变长度的字符串.最多8,000个字符. varchar ...
- 最近在玩linux时 yum 遇到了问题
主要是软件源出现了问题 我做的方式可能比较粗暴 ls -l /etc/yum.repos.d/ /*查看软件源*/ rm -rf /etc/yum.repos.d/ /*全删了*/ m ...
- Spring MVC初始化参数绑定
初始化参数绑定与类型转换很类似,初始化绑定时,主要是参数类型 ---单日期 在处理器类中配置绑定方法 使用@InitBinder注解 在这里首先注册一个用户编辑器 参数一为目标类型 proper ...
- hibernate-mapping-3.0.dtd;hibernate-configuration-3.0.dtd;hibernate.properties所在路径
hibernate-mapping-3.0.dtd 所在路径:hibernate-release-5.2.5.Final\project\hibernate-core\src\main\resourc ...