javascript中的动画的实现以及运动框架的编写(1)
大家知道js可以做出好多很漂亮的动画,看上去很神奇,其实原理很简单,今天就讨论一下js动画的实现以及如何编写可以反复重用的运动框架。
首先做一个简单的例子,我这里有一个长50px 宽20px的长条形div 现在我想让鼠标停在上面的时候这个长条变为长1000px宽20px的超级长条,然后当鼠标移开的时候再变回50px长。
下面看一下我写的代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<style type="text/css">
.div1{
width:50px;
height:20px;
background:red;
margin:4px;
}
</style>
<script type="text/javascript">
var odiv1 = document.getElementsByTagName("div");
window.onload = function(){
odiv1[0].onmouseover = function(){
odiv1[0].style.width = 1000+"px";
}
odiv1[0].onmouseout = function(){
odiv1[0].style.width = 50+"px";
}
}
</script>
</head> <body>
<div class="div1"></div>
</body>
</html>
这里可以看到一个非常死板的动画效果,50px长的div瞬间变成了1000px长,然后又瞬间变回来。
严格的说,这算是个p动画效果,动画的本质是人眼睛可以保存前1微秒看到的影响,从而将死板的动作看成是平滑的动作,我们现在就要改善这个死板的动作。
其实我们可以将如此死板的动作理解为速度太快了,一瞬间就从50变到1000了,如果我们能让他先从50变成100,然后再变成150,最后变成1000,动作必然变得更加平滑,现在我让他同样时间内只变化少量px最终变成1000的时候,就停止。我可以用一个定时器来实现这一点。
看我改善后的javascript部分的代码如下:
var odiv1 = document.getElementsByTagName("div");
window.onload = function(){
var speed = 5;
var timer = null;
odiv1[0].onmouseover = function(){
clearInterval(timer);
timer = setInterval(function(){
if(odiv1[0].offsetWidth == 1000){
clearInterval(timer);
}
else{
odiv1[0].style.width = odiv1[0].offsetWidth+speed+"px";
}
},30)
}
odiv1[0].onmouseout = function(){
clearInterval(timer);
timer = setInterval(function(){
if(odiv1[0].offsetWidth == 50){
clearInterval(timer);
}
else{
odiv1[0].style.width = (odiv1[0].offsetWidth-speed)+"px";
}
},30)
}
}
现在我们看到了一个非常平滑的动画,并且speed可以移动,虽然这样的动画效果已经让你感觉很满意了,但是,他依然不够美观,这是一个匀速运动,我们喜欢看到的是一种缓冲运动,现在我们在speed上下文章,把speed定义为距离目标越近则越小,可以实现缓冲运动。代码改善如下:
var odiv1 = document.getElementsByTagName("div");
window.onload = function(){
var timer = null;
odiv1[0].onmouseover = function(){
clearInterval(timer);
timer = setInterval(function(){
var speed = (1000-odiv1[0].offsetWidth)/8;
if(odiv1[0].offsetWidth == 1000){
clearInterval(timer);
}
else{
odiv1[0].style.width = odiv1[0].offsetWidth+speed+"px";
}
},30)
}
odiv1[0].onmouseout = function(){
clearInterval(timer);
timer = setInterval(function(){
var speed = (odiv1[0].offsetWidth-50)/8;
if(odiv1[0].offsetWidth == 50){
clearInterval(timer);
}
else{
odiv1[0].style.width = (odiv1[0].offsetWidth-speed)+"px";
}
},30)
}
}
这时候看到的就是变速运动了,这里面还存在两个小问题,首先是,代码几乎没有重用性,我们在两个事件中的代码几乎相同,所以可以封装为同一段代码。其次,speed存在小数行为,小数是我们无法容忍的,不解释……下面继续对代码进行改进。
首先,我们需要对相同代码进行封装,我们现在把目标改为不确定,也就是说我们把div想要变成多大作为参数传进函数中,既能增加div长度也能减少,同时当鼠标移开的时候div恢复原来长度。下面看封装的代码:
window.onload = function(){
var timer = null;
function startMove(target){
clearInterval(timer);
timer = setInterval(function(){
var speed = (target-odiv1[0].offsetWidth)/8;
if(odiv1[0].offsetWidth == target){
clearInterval(timer);
}
else{
odiv1[0].style.width = odiv1[0].offsetWidth+speed+"px";
}
},30)
}
var odiv1 = document.getElementsByTagName("div");
odiv1[0].onmouseover = function(){
startMove(20);
}
odiv1[0].onmouseout = function(){
startMove(50);
}
}
这段代码封装了startMove()函数,看到效果完全跟原来相同。
下面我们来解决小数的问题:
我们可以利用javascript的Math对象的方法将小数转换为整数,具体如何转换不再赘述,下面是我改善的代码:
window.onload = function(){
var timer = null;
function startMove(target){
clearInterval(timer);
timer = setInterval(function(){
var speed = (target-odiv1[0].offsetWidth)/8;
if(speed>0){
speed=Math.ceil(speed);
}
else{
speed=Math.floor(speed);
}
if(odiv1[0].offsetWidth == target){
clearInterval(timer);
}
else{
odiv1[0].style.width = odiv1[0].offsetWidth+speed+"px";
}
},30)
}
var odiv1 = document.getElementsByTagName("div");
odiv1[0].onmouseover = function(){
startMove(20);
}
odiv1[0].onmouseout = function(){
startMove(50);
}
}
现在运动框架基本成型,最后我们需要的不仅仅是对一个对象进行运动,我们有时候一个页面需要很多元素需要动画,这时候我们需要对函数进行进一步封装,把运动的对象也放进函数中进行封装。
下面是代码:
function startMove(obj,target){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var speed = (target-obj.offsetWidth)/8;
if(speed>0){
speed=Math.ceil(speed);
}
else{
speed=Math.floor(speed);
}
if(obj.offsetWidth == target){
clearInterval(obj.timer);
}
else{
obj.style.width = obj.offsetWidth+speed+"px";
}
},30)
}
window.onload = function(){
var odiv1 = document.getElementsByTagName("div");
for(var i=0;i<odiv1.length;i++){
odiv1[i].timer = null;
odiv1[i].onmouseover = function(){
startMove(this,200);
}
odiv1[i].onmouseout = function(){
startMove(this,50);
}
}
}
就这样我们建立了一个简单的运动框架实现了动画效果。并且代码具有一定的重用性。
javascript中的动画的实现以及运动框架的编写(1)的更多相关文章
- JavaScript中的各种宽高以及位置总结
JavaScript中的各种宽高以及位置总结 在javascript中操作dom节点让其运动的时候,常常会涉及到各种宽高以及位置坐标等概念,如果不能很好地理解这些属性所代表的意义,就不能理解js的运动 ...
- javascript运动框架
下面这个一个运动框架可以控制元素在一个属性上的运动,同时,可以调用回调函数. /* 获取元素某个属性的值 @obj: 对象 @attr: 属性值 */ function getStyle(obj, a ...
- javascript中的时间版运动
前面的话 速度版JS运动是指以速度为参照,随着路程的变化,时间随之变化:而时间版JS运动是指以时间为参照,随着路程的变化,速度随着变化.相较而言,时间版JS运动更为常用.JQ的animate就是时间版 ...
- 原生JavaScript中动画与特效的实现原理
现如今,许多页面上均有一些动画效果.适当的动画效果可以在一定程度上提高页面的美观度,具有提示效果的动画可以增强页面的易用性. 实现页面动画的途径一般有两种. 一种是通过操作JavaScript间接操作 ...
- CSS3中的动画效果记录
今天要记录的是CSS3中的三种属性transform.transition以及animation,这三个属性大大提升了css处理动画的能力. 一.Transform 变形 CSS中transform ...
- 好程序员技术教程分享JavaScript运动框架
好程序员技术教程分享JavaScript运动框架,有需要的朋友可以参考下. JavaScript的运动,即让某元素的某些属性由一个值变到另一个值的过程.如让div的width属性由200px变到400 ...
- 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结
史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...
- JavaScript 基础入门11 - 运动框架的封装
目录 JavaScript 运动原理 运动基础 简单运动的封装 淡入淡出 不同属性的设置 多属性值同时运动 运动回调,链式运动 缓冲运动 加入缓冲的运动框架 案例1 多图片展开收缩 运动的留言本 Ja ...
- 【repost】JavaScript完美运动框架的进阶之旅
运动框架的实现思路 运动,其实就是在一段时间内改变left.right.width.height.opactiy的值,到达目的地之后停止. 现在按照以下步骤来进行我们的运动框架的封装: 匀速运动. 缓 ...
随机推荐
- 1004 Anagrams by Stack
考察DFS的应用,用栈描述字符串的变化过程. #include <stdio.h> #include <string.h> int len1,len2; ],str2[],st ...
- 伪静态(URL重写)
伪静态在可以使用数据库提供更强大的功能的同时,将很长很复杂的链接变成简短的静态链接形式,迎合搜索引擎方便搜索引擎蜘蛛(Spider)来抓取网页上的相关内容,提高页面被搜索引擎索引收录的比率,为用户提供 ...
- 理解 backbone.js 中的 bind 和 bindAll 方法,关于如何在方法中指定其中的 this,包含apply方法的说明[转载]
转载自:http://gxxsite.com/content/view/id/132.html 在backbone.js的学习过程中,被bind和bindAll弄得有点晕,这里包括underscore ...
- Java 学习 第四篇;面向对象(1)
1:关于继承为了保证父类的良好封装性,不会被子类随意改变,设计父类时通常隐藏父类的内部数据,把父类属性改为private如果父类中可以被重写,但不希望被其他类自由访问可用protected修饰;2:什 ...
- c++ ifstream ofstream 文件流
#include <fstream>ofstream //文件写操作 内存写入存储设备 ifstream //文件读操作,存储设备读区到内存中fstream //读写操作,对打开的文件可进 ...
- UESTC_秋实大哥与妹纸 2015 UESTC Training for Data Structures<Problem F>
F - 秋实大哥与妹纸 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 1500/1500KB (Java/Others) Submit ...
- netstat和telnet命令在Windows7中的用法(转载)
在网络方面我们常常会用到如下命令: (1)ping命令:我们常常用来判断2台或2台以上的机器间是否网络连通. ping 192.168.1.88 -t 如果想看任何命令的参数是什么意思,我们只需要:命 ...
- Zookeeper 3、Zookeeper工作原理(详细)
1.Zookeeper的角色 » 领导者(leader),负责进行投票的发起和决议,更新系统状态 » 学习者(learner),包括跟随者(follower)和观察者(observer),follow ...
- HBase 5、Phoenix使用
1.建表 执行建表语句 $ . ../examples/stock_symbol.sql 其中../examples/stock_symbol.sql是建表的sql语句 CREATE TABLE IF ...
- GDB+GDBServer调试Linux应用程序
参考:http://blog.csdn.net/shanghaiqianlun/article/details/7820401 一.gdb+gdbserver总体介绍 远程调试环境由宿主机GDB和目标 ...