JS——动画

来源:互联网 发布:淘宝店铺找谁可以装修 编辑:程序博客网 时间:2024/05/21 18:35

运动实现思路


1. 速度(匀速)

改变left、right、width、height、opacity


实例1(速度)

做一个侧栏分享的案例

思路

容器设置相对定位。

内容原本的left是负值,设置一个定时器,每隔一段时间,露出一点来。

直至offsetLeft为0,结束计时器。


代码

window.onload=function(){            var oDiv=document.getElementById("div1");            oDiv.onmouseover=function(){                    startMove(0);                }            oDiv.onmouseout=function(){                    startMove(-200);                }            }        var timer=null;        function startMove(iTarget){            clearInterval(timer);            var oDiv=document.getElementById("div1");            timer=setInterval(function(){                var speed=0;                // 判断该 增 or 减 left                if(oDiv.offsetLeft > iTarget){                    speed = -10;                }else{                    speed = 10;                }                //判断停止或继续运动                if(oDiv.offsetLeft==iTarget){                    clearInterval(timer);                }else{                    oDiv.style.left=oDiv.offsetLeft+speed+"px";                }            },30)        }


实例2(透明度)


透明度css属性

    filter:alpha(opacity:30); 针对 IE8 以及更早的版本 0-100    opacity:0.3; 0~1


思路

跟上面的例子一样,只不过最后操作的属性是透明度。


实例

window.onload=function(){            var oDiv=document.getElementById("div1");            oDiv.onmouseover=function(){                    startMove(100);            }            oDiv.onmouseout=function(){                    startMove(30);            }        }        var timer=null,            alpha=30;        function startMove(iTarget){            clearInterval(timer);            var oDiv=document.getElementById("div1");            //每次运动时,先把变量speed清零            timer=setInterval(function(){                var speed=0;                if(alpha > iTarget){                    speed = -10;                }else{                    speed = 10;                }                if(alpha==iTarget){                    clearInterval(timer);                }else{                    alpha+=speed;                    oDiv.style.filter = "alpha(opacity:'+alpha+')";                    oDiv.style.opacity = alpha/100;                }            },30)        }


2. 缓冲(渐慢)


思路

speed = (目标值和当前值的差)/ 数值

当差值大的时候,速度就快。

当差值小的时候,速度就慢。

特别注意

上面的计算会导致小数点的出现,浏览器是向下取整的小数点一直被忽略。

结果,就会导致一直达不到我们所设定的目标值。

因此,我们需要做一些处理。


实例

window.onload=function(){            var oDiv=document.getElementById("div1");            oDiv.onmouseover=function(){                    startMove(0);                }            oDiv.onmouseout=function(){                    startMove(-200);                }            }        var timer=null;        function startMove(iTarget){            clearInterval(timer);            var oDiv=document.getElementById("div1");            timer=setInterval(function(){                var speed = (iTarget-oDiv.offsetLeft)/20;                    speed = speed>0?Math.ceil(speed):Math.floor(speed);                if(oDiv.offsetLeft==iTarget){                    clearInterval(timer);                }else{                    oDiv.style.left=oDiv.offsetLeft+speed+"px";                }            },30)        }


3. 多物体运动


思路

  1. 遍历需要元素,分别加上事件。

  2. 由于是多物体,所以需要区分物体是哪一个,把this作为参数也传进去。

  3. 每一个物体都应该有子集专属的定时器,所以在循环体设置定时器。


特别注意

在实际工作中,物体肯定会有边框、内外边距。继续使用offset类的属性,将会导致bug出现,所以我们需要获取物体自身的宽高等尺寸属性。

在代码内,封装了一个getStyle方法,IE是通过currentStyle属性获取元素属性的,而其余浏览器则是通过getComputedStyle()方法取得元素属性的。


实例

window.onload=function(){            var aLi = document.getElementsByTagName("li");            //遍历元素            for(var i=0;i<aLi.length;i++){                //每个元素都创建自己的定时器为null                aLi[i].timer=null;                aLi[i].onmouseover=function(){                    //this作为参数传入                    startMove(this,400);                }                aLi[i].onmouseout=function(){                    startMove(this,200);                }            }        }        //获取属性        function getStyle(obj,attr){            if(obj.currentStyle){   //ie                return obj.currentStyle[attr];            }            else{  //W3C                return getComputedStyle(obj,false)[attr];            }        }        function startMove(obj,iTarget){            //清除定时器            clearInterval(obj.timer);            obj.timer = setInterval(function(){                var icur = parseInt(getStyle(obj,'width'));                var speed = (iTarget-icur)/8;                    speed = speed>0?Math.ceil(speed):Math.floor(speed);                if(icur==iTarget){                    clearInterval(obj.timer);                }else{                    obj.style.width = icur+speed+"px";                }            },30)        }



4. 链式运动


在运动函数内加一个参数,让它执行一个回调函数。

第一版代码

 <!doctype html><html><head>    <meta charset="utf-8">    <title>链式动画</title>    <style>        *{            margin:0;            padding:0;        }        ul,li {            list-style:none;        }        ul li {            width:200px;            height:100px;            background:yellow;            margin-bottom:20px;            border:4px solid #000;            filter:alpha(opacity:30);            opacity:0.3;         }    </style>    <script>        window.onload=function(){            var Li=document.getElementById('li1');            Li.onmouseover= function(){                startMove(Li,'width',400,function(){                    alert("done");                });            }                   }        function getStyle(obj, atttr) {            if(obj.currentStyle) {                return obj.currentStyle[atttr];            } else {                return getComputedStyle(obj, false)[atttr];            }        }        function startMove(obj, attr, iTarget, fn) {            clearInterval(obj.timmer);            obj.timmer = setInterval(function() {                var icur = 0;                if(attr == 'opacity') {                    icur = Math.round(parseFloat(getStyle(obj, attr)) * 100);                } else {                    icur = parseInt(getStyle(obj, attr));                }                var speed = (iTarget - icur) / 8;                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);                if(icur == iTarget) {                    clearInterval(obj.timmer);                    if(fn) {                        fn();                    }                } else {                    if(attr == 'opacity') {                        obj.style.opacity = (icur + speed) / 100;                    } else {                        obj.style[attr] = (icur + speed) + 'px';                    }                }            }, 30);        }    </script></head>    <body>        <ul>            <li id="li1"></li>        </ul>    </body></html>


这一版方案存在以下问题:

在屏幕缩放比例为非100%的时候,有可能会导致元素计算宽度问题,从而导致最终无法进行链式运动。


解决思路:


1. 既然是屏幕缩放比例出现问题,那我首先可以提醒一下用户,请他把屏幕分辨率调整为100%

如果是Chrome和FireFox,可以使用window.devicePixelRatio接口查询;

IE使用window.screen.deviceXDPI 和 window.screen.logicalXDPI ;

其他浏览器使用window.outerWidth 和 window.innerWidth 这两个属性。


2. 使用rem相对单位

使用rem相对单位,并且把iTarget变为函数内部变量,传入参数改变为倍数。

这里面有一个问题,getStyle函数获取属性的单位是px,而不是rem,所以需要对icur变量进行处理。

由于现在iTarget是不固定的值,判断条件应该改为icur和最终值的比较。


第二版代码

<!doctype html><html><head>    <meta charset="utf-8">    <title>链式动画</title>    <style>        *{            margin:0;            padding:0;        }        html {            font-size:20px;        }        ul,li {            list-style:none;        }        ul li {            width:10rem;            height:5rem;            background:yellow;            margin-bottom:20px;            border:4px solid #000;            filter:alpha(opacity:30);            opacity:0.3;         }    </style>    <script>        window.onload=function(){            detectZoom ();            var Li=document.getElementById('li1');            Li.onmouseover= function(){                startMove(Li,'width',2,function(){alert("done");});            }                   }        function detectZoom (){           var ratio = 0,            screen = window.screen,            ua = navigator.userAgent.toLowerCase();           if (window.devicePixelRatio !== undefined) {              ratio = window.devicePixelRatio;          }          else if (~ua.indexOf('msie')) {              if (screen.deviceXDPI && screen.logicalXDPI) {              ratio = screen.deviceXDPI / screen.logicalXDPI;            }          }          else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {            ratio = window.outerWidth / window.innerWidth;          }           if (ratio){            if(ratio !=1){                alert("为了您的使用体验,请把浏览器缩放比例调整至100%");            }          }        }           function getStyle(obj, atttr) {            if(obj.currentStyle) {                return obj.currentStyle[atttr];            } else {                return getComputedStyle(obj, false)[atttr];            }        }        function startMove(obj, attr, beishu, fn) {            clearInterval(obj.timmer);            obj.timmer = setInterval(function() {                var icur = 0;                if(attr == 'opacity') {                    icur = Math.round(parseFloat(getStyle(obj, attr)) * 100);                } else {                    icur = parseInt(getStyle(obj, attr))/20;                }                var iTarget = icur*beishu;                var speed = (iTarget - icur) / 15;                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);                if(icur >= 20 ) {                    clearInterval(obj.timmer);                    if(fn) {                        fn();                    }                } else {                    if(attr == 'opacity') {                        obj.style.opacity = (icur + speed) / 100;                    } else {                        obj.style[attr] = (icur + speed) + 'em';                    }                }            }, 30);        }    </script></head>    <body>        <ul>            <li id="li1"></li>        </ul>    </body></html>


5. 同时运动

使用json储存我们的属性和目标值。

另外,停止条件改为所有属性变为目标值。为此,我们声明一个变量flag,还有属性未达到目标值,flag为false,不能停止。

实例代码

<!doctype html><html><head>    <meta charset="utf-8">    <title>同时运动</title>    <style>        *{            margin:0;            padding:0;        }        ul,li {            list-style:none;        }        ul li {            width:200px;            height:100px;            background:yellow;            margin-bottom:20px;            border:4px solid #000;            filter:alpha(opacity:30);            opacity:0.3;         }        </style>    <script>        window.onload=function(){            var oLi=document.getElementById("li1");            oLi.onmouseover=function(){                startMove(oLi,{width:400,height:201,opacity:100});            }            oLi.onmouseout=function(){                startMove(oLi,{width:200,height:100,opacity:30});            }        }        function getStyle(obj,attr){            if(obj.currentStyle){   //ie                return obj.currentStyle[attr];            }            else{  //W3C                return getComputedStyle(obj,false)[attr];            }        }        function startMove(obj,json,fn){            clearInterval(obj.timer);            obj.timer = setInterval(function(){                var flag = true;//假设所有的运动都到达了目标值                for(var attr in json){                    //1.取当前的值                    var icur=0;                    if(attr == 'opacity'){                        icur = Math.round(parseFloat(getStyle(obj,attr))*100);                    }                    else{                        icur = parseInt(getStyle(obj,attr));                    }                    //2.算速度                    var speed = (json[attr]-icur)/8;                        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)+')';                            obj.style.opacity=(icur+speed)/100;                        }                        else                        {                            obj.style[  attr] = icur+speed+"px";                        }                       }                if(flag)                {                    clearInterval(obj.timer);                    if(fn){                        fn();                    }                }            },30)        }    </script>    </head>    <body>        <ul>            <li id="li1"></li>        </ul>    </body></html>