九、多属性同时运动

前面的例子都是每个属性单独运动,如果想要多属性同时运动怎么办?比如,我想要一个div的onmouseover事件中宽和高同时变化。下面这个函数是单独变宽:

window.onload=function(){
            var ob1=document.getElementById('div1');
            ob1.onmouseover=function(){
                startMove(ob1,'width',400);
            }
}

有一个想法就是在startMove下面再加一个startMove:

window.onload=function(){
            var ob1=document.getElementById('div1');
            ob1.onmouseover=function(){
                startMove(ob1,'width',400);

       startMove(ob1,'height',400);
            }
}

事实证明这种想法是错误的,这么写只有高变了,而宽没变。为什么呢?因为startMove函数的起初就是关闭定时器,当第一个startMove函数刚刚开始执行时,第二个startMove已经开始执行,第二个startMove的关闭定时器功能将第一个startMove的定时器覆盖掉了,所以物体的宽无法变化,变的只有高。那么如何解决?这里需要用到json:

var json={a:12,b:13};
for(var i in json){
    alert(i);
    alert(json[i]);
}

json里的值是成对出现的,每一对为变量和变量的值。可以用for in循环来获取每一对的变量以及对应的值。上面程序依次弹出a,12,b,13 。

下面来看一下stareMove框架,发现参数里的“属性”和“目标值”是一对值,也就是说一个startMove只能实现一对值的变化。如何实现多对值的变化?来看看这个样子的startMove :

startMove(obj,{attr1:target1,attr2:target2},fn),蓝色部分就是json的形式,所以在原来的startMove基础上,将蓝色部分换成json ;将程序中的target换成json[attr](是哪个属性,就是那个属性的目标值)。改变完的startMove函数如下:(第1,4,13,16行做了改动)

 function startMove(obj,json,fn) {//元素,改变的样式属性,达到的目标值,回调函数
clearInterval(obj.timer);
obj.timer=setInterval(function(){
for(var attr in json){
//1.取当前值
var icur=0;//icur返回物体样式属性值的大小
if (attr=='opacity') {//如果属性是透明度,透明度的返回值是零点几的小数
icur=Math.round(parseFloat(getStyle(obj,attr))*100);//round函数避免透明度值在小数之间来回跳动
} else {
icur=parseInt(getStyle(obj,attr));
}
//2.算速度
var speed=(json[attr]-icur)/8;//分母为比例系数K,可调
speed=speed>0?Math.ceil(speed):Math.floor(speed);//缓冲速度要取整,不然移动不到终点就停止
//3.检测运动是否停止
if (icur==json[attr]) {
clearInterval(obj.timer);
if(fn){//上一个运动停止后判断一下是否还有下一个运动
fn();
}
} else {
if (attr=='opacity') {
obj.style.filter='alpha(opacity:'+(icur+speed)+')';//IE浏览器
obj.style.opacity=(icur+speed)/100;//火狐浏览器
} else {
obj.style[attr]=icur+speed+'px';
}
}
}
},30)
}

下面是一个div调用startMove函数达到宽高同时变化的效果:

 <style type="text/css">
#div1{
width: 200px;
height: 200px;
background: red;
border: 2px solid black;
filter: alpha(opacity:30);
opacity: 0.3;
}
</style>
 <script type="text/javascript">
window.onload=function(){
var ob1=document.getElementById('div1');
ob1.onmouseover=function(){
startMove(ob1,{width:400,height:400});//json格式
}
}
</script>

可以再加一对透明度,实现宽、高、透明度同时变化:

 <script type="text/javascript">
window.onload=function(){
var ob1=document.getElementById('div1');
ob1.onmouseover=function(){
startMove(ob1,{width:400,height:400,opacity:100});
}
}
</script>

本框架存在的问题:当我想要把宽变为201,高变为400,透明度变为100时,会出现一个问题:宽确实变成201,但是高和透明度还远远未达到目标值,运动就停止了。原因是17行的关闭定时器,原程序里只要有一个属性值达到目标值,就关闭定时器,并没有对每个属性是否达到目标值都做判断。所以出现了当宽达到了目标值,高和透明度还没有达到目标值的时候定时器就关闭了。解决办法:我们需要判断所有的属性都达到目标值时才关闭定时器。(第2行,第17行以后有改动)

 function startMove(obj,json,fn) {//元素,改变的样式属性,达到的目标值,回调函数
var flag=true;//定义一个标杆,假设所有运动都达到了目标值
clearInterval(obj.timer);
obj.timer=setInterval(function(){
for(var attr in json){
//1.取当前值
var icur=0;//icur返回物体样式属性值的大小
if (attr=='opacity') {//如果属性是透明度,透明度的返回值是零点几的小数
icur=Math.round(parseFloat(getStyle(obj,attr))*100);//round函数避免透明度值在小数之间来回跳动
} else {
icur=parseInt(getStyle(obj,attr));
}
//2.算速度
var speed=(json[attr]-icur)/8;//分母为比例系数K,可调
speed=speed>0?Math.ceil(speed):Math.floor(speed);//缓冲速度要取整,不然移动不到终点就停止
//3.检测运动是否停止
if (icur!=json[attr]) {//如果不是所有的运动都达到目标值
flag=false;
}
if (attr=='opacity') {//没达到目标值的继续运动
obj.style.filter='alpha(opacity:'+(icur+speed)+')';//IE浏览器
obj.style.opacity=(icur+speed)/100;//火狐浏览器
} else {
obj.style[attr]=icur+speed+'px';
} if(flag){//如果所有的运动都达到了目标值,再关闭定时器,然后看看有没有链式运动
clearInterval(obj.timer);
if(fn){
fn();
}
}
} },30)
}

现在这个改动完的框架就是完美框架了,一些网站上常用的小动画就可以用这个框架实现。

js动画学习(五)的更多相关文章

  1. 【06-23】js动画学习笔记01

    <html> <head> <style> * { margin:0; padding:0; } #div1{ width:200px; height:200px; ...

  2. js动画学习(四)

    七.多属性封装函数 前面分别介绍了单独改变单一属性值得动画,从本节起开始介绍多属性封装函数,一个函数搞定多种属性值的改变. 首先介绍一个很重要的函数getStyle(),这个函数返回一个元素的当前属性 ...

  3. js动画学习(二)

    四.简单动画之缓冲运动 实现速度的缓冲,即不同位置的速度不同,越靠近目标值速度越小,所以速度值与目标值与当前值之差成正比.这里要注意一个问题就是物体在运动中速度是连续变化的,不是按照整数变化的,当物体 ...

  4. js动画学习(一)

    一.运动框架实现思路 1.匀速运动(属性值匀速变化)(改变 left, right, width, height, opacity 等): 2.缓冲运动(属性值的变化速度与当前值与目标值的差成正比): ...

  5. js动画学习(三)

    五.多物体变宽 这里面要注意由于物体变多了,需要给每个物体各配备一个定时器,否则如果只有一个定时器的话,当鼠标在不同物体之间快速滑动时,不同的物体就会出现争抢的现象.所以timer前要加obj. fu ...

  6. js动画学习笔记

    <html> <head> <meta charest="utf-8"> <title>test</title> < ...

  7. SVG 学习<五> SVG动画

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  8. WebGL three.js学习笔记 加载外部模型以及Tween.js动画

    WebGL three.js学习笔记 加载外部模型以及Tween.js动画 本文的程序实现了加载外部stl格式的模型,以及学习了如何把加载的模型变为一个粒子系统,并使用Tween.js对该粒子系统进行 ...

  9. [学习笔记]js动画实现方法,作用域,闭包

    一,js动画基本都是依靠setInterval和setTimeout来实现 1,setInterval是间隔执行,过一段时间执行一次代码 setInterval(function(){},500);即 ...

随机推荐

  1. [原]基于CAS实现单点登录(SSO):登录成功后,cas client如何返回更多用户信息

    从cas server登录成功后,默认只能从casclient得到用户名.但程序中也可能遇到需要得到更多如姓名,手机号,email等更多用户信息的情况. cas client拿到用户名后再到数据库中查 ...

  2. MFC 可以设置背景色、字体、字体颜色、透明背景的 Static 静态文本控件

    MFC库里没有符合这个条件的控件,于是我自己写了一个,初步测试有效. 注:可以设置透明背景,但还不能做到透明度设置(如50%透明度) 如果设置了背景色,就不保留透明背景 默认背景色是透明的 [cpp] ...

  3. Java 覆盖测试工具 :EclEmma

    http://www.eclemma.org/installation.html#manual EclEmma 2.2.1 Java Code Coverage for Eclipse Overvie ...

  4. enumerate小技巧和列表推导式

    1.enumerate enumerate函数用于遍历序列中的元素以及它们的下标,这样你就可以通过index 直接定位你的数据了. 之前对list操作的时候,即想取到下表,又想取到对应值,我是这么来实 ...

  5. WebStorm 7.0 注冊码

    经測试 WebStorm 6 7均能够使用例如以下注冊码,简直就是神key啊! WebStorm 6.0 7.0 注冊码 User Name: EMBRACE   License Key: ===== ...

  6. POJ 2342 树形DP入门题

    有一个大学的庆典晚会,想邀请一些在大学任职的人来參加,每一个人有自己的搞笑值,可是如今遇到一个问题就是假设两个人之间有直接的上下级关系,那么他们中仅仅能有一个来參加,求请来一部分人之后,搞笑值的最大是 ...

  7. 关于响应式、媒体查询和media的关系 、流媒体布局flex 和em rem像素的使用 我有一些废话要讲.....

    一.什么是响应式 随着移动端越来遇火 网站的布局成为一个热议的话题 有的人喜欢用手机浏览网站.有的人喜欢用paid浏览网站.有人喜欢用电脑浏览网站 那么问题来了 我们怎么样才能使用一套css样式 完成 ...

  8. 异常java.lang.IllegalStateException的解决

    在初始化viewPagerAdapter时,显示异常.从网上找了找有两类这样的问题,一种是说给一个视图设置了两个父类,如: TextView tv = new TextView();layout.ad ...

  9. iOS 在当前控制器中发送短信

    - (void)showMessageViewWithTel:(NSString *)tel { if( [MFMessageComposeViewController canSendText] ){ ...

  10. Android ActionBar详解(二)--->使用ActionBar显示选项菜单

    MainActivity如下: package cc.testsimpleactionbar1; import android.os.Bundle; import android.app.Activi ...