zoukankan      html  css  js  c++  java
  • JavaScript 运动(缓冲运动,多物体运动 ,多物体多值运动+回调机制)

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

     1 function startMove(dom, speed,targetPosetion){     //dom : 运动对象, speed :运动速度 targetPosition : 到达目标位置
     2   clearInterval(timer);                           //防止定时器叠加,先清除定时器。
     3    speed = targetPosetion - dom.offsetLeft > 0 ? speed : -speed;   
     4                                                    //断物体到移动的目标位置的左边还是右边,左边速度是正的,右边速度是负的。
     5   timer = setInterval(function(){               //设置定时器。变量timer要定义在函数外面。
     6     if(Math.abs(targetPosetion - dom.offsetLeft ) < Math.abs(speed)){  
     7       clearInterval(timer);                   //当目位置减去物体偏移量小于定时器移动的位置(因为在移动就超出了目标位置),清除定时器
     9       dom.style.left = targetPosetion + "px"; //因为距离目标位置还有一小段距离,直接让物体等于目标位置就行
    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 () {                             
     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 }
    6:当目标位置 - 物体偏移量小于除数时,speed就等于小数了, 但是偏移量都是整数,就会自动的取舍值,例如:dom.style.left = 355.24px 实际会转换成dom.style.left = 355px; 导致最后怎么加都是原来的那个整数。所以只要有小数就向上取整(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,0.5);     
     2 function startMove(dom, targetOpacity) {
     3   clearInterval(timer);  targerOpacity = targetOpacity * 100;  //透明度的范围是0-1,而缓冲变化最小变化是1 需要把缓冲范围变大(扩大100倍)。
     4   var speed = null,current = null;
     5   timer = setInterval(function () {
     6     current = parseFloat(getStyle(div,'opacity')) * 100;
     7     console.log(current);
     8     speed = (targetOpacity - current) / 10;
     9     speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
    10     if (current == targetOpacity) {
    11       clearInterval(timer);
    12     } else {
    13     dom.style.opacity = (current + speed) / 100;             //当赋值时需要缩小100倍
    14     }
    15   }, 30)
    16 }
     
    多物体运动
     
    例:4个div,鼠标移入到那个div,宽度做缓冲运动移动到400;移除宽度变为100。
    下面的代码。橙色的部分有timer变为dom自己的属性dom.timer,在上面定义timer的时候,
    定义的timer是在函数外面的,4个div共用一个timer定时器,当鼠标移入第一个div时,开启一个定
    时器,移出div时,又开启一个定时器。当快速从第一个div移到第二个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)
            }
     
    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     else 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, {  400,height: 400,left: 200,top: 300,opacity: 50}, function () {
    5                 startMove(divTwo, {  400, height: 400, left: 200, top: 300, opacity: 50 }, function () {
    6                     alert(555);
    7                 })
    8             })
    9         }
  • 相关阅读:
    使用canvas实现擦玻璃效果
    安装jdk For Windows
    墙裂推荐4款js网页烟花特效
    再次推荐一款逼真的HTML5下雪效果
    HTML5播放暂停音乐
    周末web前端练习
    Javascript贪食蛇小游戏
    jquery实现更多内容效果
    jQuery省市区三级联动插件
    Web前端测试题
  • 原文地址:https://www.cnblogs.com/jiaobaba/p/10536332.html
Copyright © 2011-2022 走看看