欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JavaScript 运动(缓冲运动,多物体运动 ,多物体多值运动+回调机制)

程序员文章站 2024-01-24 14:30:40
匀速运动 (当需要物体做匀速运动直接调用statMove函数) 缓冲运动(越接近目标,速度越慢) 缓运运动比直线运动视觉性更好,所以很常用 1 function startMove(dom, targetPosetion) { 2 clearInterval(timer); 3 var speed ......

匀速运动   (当需要物体做匀速运动直接调用statmove函数)

 

 1 function startmove(dom,targetposetion){ //dom : 运动对象,targetposition : 到达目标位置
 2   clearinterval(timer);                                // 防止定时器叠加,先清除定时器。
 3   var speed = targetposetion - dom.offsetleft > 0 ? 7 : -7;   
 4        //断物体到移动的目标位置的左边还是右边,左边速度是正的,右边速度是负的。
 5   timer = setinterval(function(){   //设置定时器。变量timer要定义在函数外面。
 6     if(math.abs(targetposetion - dom.offsetleft ) < math.abs(speed)){  
 7       clearinterval(timer);         
 8            //当目位置减去物体偏移量小于定时器移动的位置(因为在移动就超出了目标位置),清除定时器
 9       dom.style.left = targetposetion + "px";   
10                 //因为距离目标位置还有一小段距离,直接让物体等于目标位置就行
11     }else{
12       dom.style.left = dom.offsetleft + speed + "px";
13     }
14   },30);
15 }
缓冲运动(越接近目标,速度越慢
缓运运动比直线运动视觉性更好,所以很常用
 1 function startmove(dom, targetposetion) { 
 2   clearinterval(timer);
 3   var speed = null;
 4   timer = setinterval(function () {                              //设置定时器。变量timer要定义在函数外面。
 5     speed = (targetposetion - dom.offsetleft) /10;    
 6     speed = speed > 0 ? math.ceil(speed) : math.floor(speed);     
 7     if(dom.offsetleft == targetposetion){
 8       clearinterval(timer);
 9     }else{
10       dom.style.left = dom.offsetleft + speed + "px";
11     }
12   }, 30)
13 }
5: 目标位置 - 物体偏移量(因为目标位置固定的,但是物体偏移量越来越大,所以会越来越慢)第10行的dom.offsetleft和第5行负的dom.offsetleft互相抵消掉了,dom.style.left直接等于目标位置(速度太大),所以要除以一个小数。
6:当目标位置 - 物体偏移量小于除数时,speed就等于小数了, 但是偏移量都是整数,就会自动的取舍值,例如:dom.style.left = 35.6px 实际会转换成dom.style.left = 36px;所以只要有小数就向上取整(math.ceil()),加上1。当是负值的时候就下取整(math.floor()).因为当speed是小数时,就会被取整。所以最后是一个像素一个像素加上去的,所以物体的偏移量正好等于目标位置时就清除定时器。
 
颜色渐变的缓冲运动
因为让当前的颜色渐变需要让当前的opacity增加或减少,获取当前的透明度opacity可以用计算样式window.getcomputedstyle
计算样式只读,返回的都是绝对值,没有相对单位
1 function getstyle(dom,attr){
2   if(window.getcomputedstyle){
3     return window.getcomputedstyle(dom,null)[attr];
4   }
5   else{
6     return dom.currentstyle[attr]; //ie8不兼容,ie独有属性currentstyle
7   }
8 }
让物体透明度缓冲变化
 1 startmove(div,25);
 2 function startmove(dom, targetposetion) {
 3   clearinterval(timer);
 4   var speed = null,current = null;
 5   timer = setinterval(function () {
 6     current = parsefloat(getstyle(div,'opacity')) * 100;
 7     console.log(current);
 8     speed = (targetposetion - current) / 10;
 9     speed = speed > 0 ? math.ceil(speed) : math.floor(speed);
10     if (current == targetposetion) {
11       clearinterval(timer);
12     } else {
13     dom.style.opacity = (current + speed) / 100;
14     }
15   }, 30)
16 }

 

因为透明度的取值范围是0-1,把缓冲范围变大,调用函数时和获取当前透明度值时扩大100倍,增大缓冲区间,当给opacity赋值的时候缩小100倍。
 
多物体运动
 
4个div,移入到那个div,宽度做缓冲运动移动到400;移除宽度变为100。
下面的代码。橙色的部分有timer变为dom自己的属性dom.timer,
在上面定义timer的时候,定义的timer是在函数外面的,4个div共用一个timer定时器
当移入一个div时,开启一个定时器,移出div时,又把上一个定时器给清除了,重新开启了一个定时器。
当从上一个div快速移入一个新的div时,还没等回到100,开启的那个新的div。就把上一个div给清除了。
所以解决这个问题,就是在每个div上都加一个定时器。
当清理定时器的时候也是清理自己的定时器,不会影响其他的,就在每个元素上加上timer属性。
function startmove(dom, targetposetion) {
clearinterval(dom.timer);
var speed = null;
dom.timer = setinterval(function () {
current = parsefloat(getstyle(dom, 'width')); //用计算样式获取当前宽度值。
speed = (targetposetion - current) / 10;
speed = speed > 0 ? math.ceil(speed) : math.floor(speed);
console.log(speed, current);
if (current == targetposetion) {
clearinterval(dom.timer);
} else {
dom.style.width = current + speed + "px";
}
}, 30)
}
var div = document.getelementsbytagname('div');
for (var i = 0; i < div.length; i++) {
div[i].onmouseenter = function () {
startmove(this, 400)
}
div[i].onmouseleave = function(){
startmove(this,100);
}
}
多物体不同属性运动
 1 function startmove(dom , attr , target){
 2   clearinterval(dom.timer);
 3   dom.timer = setinterval(function(){
 4     var current = null,speed = null;
 5     if(attr == 'opacity'){
 6       current = parsefloat(getstyle(dom,attr)) * 100;
 7      }else{
 8       current = parsefloat(getstyle(dom,attr));
 9     }
10     speed = (target - current) / 10;
11     speed = speed > 0 ? math.ceil(speed) : math.floor(speed);
12     if(current == target){
13       clearinterval(dom.timer);
14     }
15     if(attr == 'opacity'){
16       dom.style.opacity = (current + speed) / 100;
17     }else{
18       dom.style[attr] = (current + speed) + "px";
19     }
20   },30)
21 }
22  
23 var div = document.getelementsbytagname('div');
24 div[0].onmouseenter = function(){
25   startmove(this,'width',400);
26 };
27 div[1].onmouseenter = function(){
28   startmove(this,'height',400);
29 };
30 div[2].onmouseenter = function(){
31   startmove(this,'borderwidth',20);
32 };
33 div[3].onmouseenter = function(){
34   startmove(this,'opacity',50);
35 };

多物体多值运动 + 回调机制 

 

function startmove(dom, targetobj, callback) {
            clearinterval(dom.timer);
            dom.timer = setinterval(function () {
                var stop = true;
                var speed = null, current = null;
                for (var prop in targetobj) {
                    if (prop == 'opacity') {
                        current = parsefloat(getstyle(dom, prop))*100;
                    } else {
                        current = parsefloat(getstyle(dom, prop));
                    }
                    speed = (targetobj[prop] - current) / 10;
                    speed = speed>0?math.ceil(speed):math.floor(speed);
                    if (prop == 'opacity') {
                        dom.style.opacity = (current + speed) / 100;
                    } else {
                        dom.style[prop] = (current + speed) + "px";
                    }
                    if (targetobj[prop] != current) {
                        stop = false;
                    }
                }
                if (stop == true) {
                    clearinterval(dom.timer);
                    typeof callback == 'function' && callback();
                }
            }, 30);
        }

//让多物体多值运动,由于多值就可以用对象来装。
startmove(dom, targetobj, callback)接收3个参数,运动对象,想要改变的多值属性对象,回调函数
跟上面一样一地步清除定时器,然后设置定时器,用for in 循环传过来的对象属性,
如果传过来的是opacity 就要扩大100倍,不是就正常调用上面getstyle()方法,返回一个计算属性。
设置一个锁,每次定时器执行时定义一个变量stop = true 可以停止,
当for in 循环时,判断如果有一个当前值不等于目标值的时候,就让stop = false。不可以停止
for in 结束,stop == true 的时候就代表所有的值都到达目标值,这时候就可以清空定时器。这个运动过程结束,调用回调函数


1      var divone = document.getelementbyid('one');
2         var divtwo = document.getelementbyid('two');
3         divone.onclick = function () {
4             startmove(this, { width: 400,height: 400,left: 200,top: 300,opacity: 50}, function () {
5                 startmove(divtwo, { width: 400, height: 400, left: 200, top: 300, opacity: 50 }, function () {
6                     alert(555);
7                 })
8             })
9         }