第四十二课:基于CSS的动画引擎
由于低版本浏览器不支持css3 animation,因此我们需要根据浏览器来选择不同的动画引擎。如果浏览器支持css3 animation,那么就使用此动画引擎,如果不支持,就使用javascript的动画引擎。
首先,我们看一下判定条件,方便切换。前面说过,浏览器把所有事件类型的构造器放在window上,只不过不可遍历。我们用Object.getOwnPropertyNames(window),可以得到window对象中的所有属性,然后再filter一下,就能得到所有的事件构造器了。最后,我们通过判断如果存在window.AnimationEvent或window.WebKitAnimationEvent就可以使用我们基于css的动画引擎了。
Object.getOwnPropertyNames(object)方法返回object对象自己的属性的名称。 一个对象的自己的属性是指直接对该对象定义的属性,而不是从该对象的原型继承的属性。返回值是一个数组,其中包含object对象自己的属性的名称,而且object的可枚举的和不可枚举的属性和方法都返回。 若要仅返回可枚举的属性和方法的名称,可使用 Object.keys 函数。
另一个方法也可以判断,通过判定有没有keyframe样式规则的构造器。它也是放在window上的,我们可以通过这样的等于来判断:var ok = window.MozCSSKeyframeRule || window.WebKitCSSKeyframeRule || window.CSSKeyframeRule;
用css实现动画引擎有以下几个好处:
(1)不用你计算原始值,它自行内部计算。
(2)颜色值不用你转换为RGB数组。
(3)如果想做动画倒带,直接设置animation-iteration-count为2,animation-direction为alternate就行了。
(4)像hide这个特效,需要我们在动画结束时,将进行动画的样式还原为初始值,在css3中,我们只需要animation-fill-mode设置为backwards就行了。
(5)对于动画的暂停和继续,其实就是控制animation-play-state的值。
css动画引擎在操作元素进行动画时,是通过添加类名或插入样式规则实现的,添加类名,我们可以通过el.classList.add()来操作。动态插入样式就有点难度了,我们需要了解相关的API。
在浏览器中,有两个元素能生产样式表,link和style。我们可以访问它们的sheet属性(样式表对象),此属性下面有一个cssRules属性(CSSRules类数组对象),它的值包含所有的样式规则。
在css中,样式规则至少有5种类型,这里我们只讲跟我们动画引擎有关的两种类型:CSSStyleRule和CSSKeyframesRule。
.move { animation:move 4s linear;} 这就是CSSStyleRule
@keyframes move { from{ margin-left:-20%;} to{margin-left:100%; } } CSSKeyframesRule
CSSStyleRule,我们可以通过它的selectorText取得指定的样式规则,比如这里的selectorText的值就是.move。
CSSKeyframesRule,我们可以通过它专有的name属性判定,比如这里的name就是move。
下面,我们来看下操作样式规则的方法:
var styleElement;
function insertCSSRule(rule){ //当插入样式规则
if(styleElement){ //如果之前已经插入过了,那么就进入if
var number = 0;
try{
var sheet = styleElement.sheet; //样式表对象
var cssRules = sheet.cssRules; //样式规则对象
number = cssRules.length; //有多少样式规则
sheet.insertRule(rule , number); //把rule插入到样式表对象中,位置在number处。
}catch(e){
$.log(e.message + rule); //抛出错误
}
}else{ //如果是第一次插入
styleElement = document.createElement("style"); //创建一个新的style
styleElement.innerHTML = rule; //把样式规则放入这个style标签中
document.head.appendChild(styleElement); //把这个style插入到页面中
}
}
function deleteCSSRule(ruleName , keyframes){ //第一个参数代表要删除的样式的名字,第二个参数代表要删除的样式是否是CSSKeyframesRule规则的,是就是true
var prop = keyframes ? "name" : "selectorText"; //这里我们假设删除的是keyframes的样式,比如:deleteCSSRule("move",true)
var name = keyframes ? "@keyframes" : "cssRule";
if(styleElement){ //当样式存在时,才能删除
var sheet = styleElement.sheet;
var cssRules = sheet.cssRules;
for(var i=0,n=cssRules.length;i<n;i++){ //遍历样式规则
var rule = cssRules[i];
if(rule[prop] ===ruleName){ //这里的prop="name",ruleName="move",因此如果sytle存在@keyframes move样式定义,rule[prop]==="move"
sheet.deleteRule(i); //删除样式表对象中的此样式规则。
break;
}
}
}
}
接着,就是三个重要的内容函数:
startAnimation,nextAnimation与stopAnimation。
startAnimation方法,用于立即执行此元素的动画,具体做法是先把传进来的参数构建成两个样式规则,第一个样式规则就是普通的CSSStyleRule,它的selectorText是一个类名,比如上面的.move,第二个样式规则是CSSKeyframesRule,它的name就是@keyframes后面的值,比如上面的move。然后,把这两个样式规则添加到页面上去。然后绑定animationend事件,最后,给要运动的元素el添加此类名,el.classList.add(className),比如上面的move。这时,el元素就会根据这两个样式规则进行动画操作,等这个动画操作结束后,就会触发animationend事件回调函数。在这个事件回调函数中,会先把元素动画的最终状态的样式全部赋给el元素的style属性中,然后移除el元素的此类名,el.classList.remove(className),这里如果不先保存动画最终状态的样式给元素el.style,当移除el元素的此类名className时,元素el会恢复到最初的状态,而不会保存动画最终状态的样式。然后移除第二个样式规则,也就是@keyframes定义的样式。最后,检查是否有其他动画元素在排队,如果有,就调用nextAnimation方法
nextAnimation(),会先判断当前是否有动画在执行,如果没有就从队列中找出一个动画对象进行动画操作(调用startAnimation),如果有,就不做任何处理。当然在队列中,如果此动画对象有延迟操作,就用setTimeout来延迟操作动画的执行。
stopAnimation用于停止动画的操作,它传入一个类名,也就是上面的move,如果当前只有一个元素引用了这个类名,那么就会在页面中删除此类名定义的样式,这里就是.move{}中的所有内容,以及keyframe定义的样式,这里就是@keyframes move{}定义的样式。如果有两个或者多个元素引用了这个类名,那么,只会把这个count减一,然后不做任何操作,直到count=0时,也就是没有元素引用这个类名时,才会删除上面的两个样式。
基于css的动画引擎就是这么简洁。但是它也有缺点,比如:它对scrollTop,scrollLeft的动画就无能为力了。此外,我们也无法对canvas元素里面的矢量图形进行动画操作。
最后,CSS3还支持transform2D和transform3D,javascript通过WebGL来实现3D效果,这些都需要用到矩阵方法进行复杂的运算,希望某一天,我加入的公司能够研究这一块。
加油!
第四十二课:基于CSS的动画引擎的更多相关文章
- NeHe OpenGL教程 第四十二课:多重视口
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 潭州课堂25班:Ph201805201 django 项目 第四十二课 后台 课程相关,用户组管理 (课堂笔记)
在线课程: 当点击进入页面时,显示所有课程 def get(self, request): courses = Course.objects.select_related('category', 't ...
- 第四十二课 KMP算法的应用
思考: replace图解: 程序完善: DTString.h: #ifndef DTSTRING_H #define DTSTRING_H #include "Object.h" ...
- python第四十二课——__str__(self)函数
4.__str__(self): 作用: 创建完对象,直接打印对象名/引用名我们得到的是对象的内存信息(十六进制的地址信息), 这串数据我们程序员并不关心,我们更希望看到的是属性赋值以后的内容(属性赋 ...
- SQL注入之Sqli-labs系列第四十一关(基于堆叠注入的盲注)和四十二关四十三关四十四关四十五关
0x1普通测试方式 (1)输入and1=1和and1=2测试,返回错误,证明存在注入 (2)union select联合查询 (3)查询表名 (4)其他 payload: ,( ,( 0x2 堆叠注入 ...
- NeHe OpenGL教程 第四十八课:轨迹球
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十二课:拾取游戏
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- centos shell编程6一些工作中实践脚本 nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志 直接送给bc做计算 gzip innobackupex/Xtrabackup 第四十节课
centos shell编程6一些工作中实践脚本 nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志 直接送给bc做计算 gzip innobacku ...
- NeHe OpenGL教程 第二十二课:凹凸映射
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
随机推荐
- jquery parent和parents,children和find
parent返回匹配元素的父元素的元素集合:parents返回匹配元素的祖先元素的元素集合. children返回匹配元素的子元素的元素集合:find返回匹配元素的后代元素的元素集合.
- HADOOP cluster some issue for installation
给namenode搭建了HA,然后根据网上的配置也配置了secondary namenode, 但是一直没有从日志中看到启动secondnary namenode,当然进程也没有. 找了很多资料,按照 ...
- NYOJ--1237最大岛屿
最大岛屿 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比海盗,你知道吧?杰克船长驾驶着自己的的 ...
- UVALive 6257 Chemist's vows --一道题的三种解法(模拟,DFS,DP)
题意:给一个元素周期表的元素符号(114种),再给一个串,问这个串能否有这些元素符号组成(全为小写). 解法1:动态规划 定义:dp[i]表示到 i 这个字符为止,能否有元素周期表里的符号构成. 则有 ...
- MySQL遇到check the manual that corresponds to your MySQL server version for the right syntax错误
用MySQL新建了一个Order表,插入了一条数据.总是显示 You have an error in your SQL syntax; check the manual thatcorrespond ...
- 如何查看windows xp系统的位数?
1.右击“我的电脑”->属性,可以看到.2.运行dxdiag,在操作系统一行可以看到.3.运行cmd,输入systeminfo,在系统类型一栏可以看到.--简单4.使用一些检测软件也可以看,像鲁 ...
- 安装grunt
1,npm install -g grunt-cli 2,npm install grunt --save 作为项目的依赖安装 这两步必不可少
- smarty变量调节器
smarty中变量调解器的作用:在模板中需要对PHP分配过来的变量在输出之前,对变量进行处理 注册变量调解器方式:$smarty->registerPlugin("modifier&q ...
- Cursor的各种效果
总结之后的Cursor的各种效果: http://sandbox.runjs.cn/show/bbwoyn0c http://css-cursor.techstream.org/ 源代码如下: < ...
- 元祖签约K2 BPM,引领绿色健康食品!
漫步街头,我们经常会被一些鲜艳的红色招牌所吸引,走进去会发现这里有一些普通西饼店不会卖的东西,比如红蛋.年糕.粽子.喜饼.等上海传统食品等......这就是元祖食品. 随着人们生活品质的不断提升,元祖 ...