JS——动画

运动实现思路


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//每个元素都创建自己的定时器为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. 链式运动


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

第一版代码

 
<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和最终值的比较。


第二版代码


<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,不能停止。

实例代码


<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>

你可能感兴趣的:(javascript,javascript,动画,实例)