• javascript中的动画的实现以及运动框架的编写(1)


    大家知道js可以做出好多很漂亮的动画,看上去很神奇,其实原理很简单,今天就讨论一下js动画的实现以及如何编写可以反复重用的运动框架。

    首先做一个简单的例子,我这里有一个长50px 宽20px的长条形div 现在我想让鼠标停在上面的时候这个长条变为长1000px宽20px的超级长条,然后当鼠标移开的时候再变回50px长。

    下面看一下我写的代码:

    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>无标题文档</title>
    <style type="text/css">
    .div1{
        width:50px;
        height:20px;
        background:red;
        margin:4px;
    }
    </style>
    <script type="text/javascript">
    var odiv1 = document.getElementsByTagName("div");
    window.onload = function(){
        odiv1[0].onmouseover = function(){
            odiv1[0].style.width = 1000+"px";
        }
        odiv1[0].onmouseout = function(){
            odiv1[0].style.width = 50+"px";
        }
    }
    </script>
    </head>
    
    <body>
    <div class="div1"></div>
    </body>
    </html>

    这里可以看到一个非常死板的动画效果,50px长的div瞬间变成了1000px长,然后又瞬间变回来。

    严格的说,这算是个p动画效果,动画的本质是人眼睛可以保存前1微秒看到的影响,从而将死板的动作看成是平滑的动作,我们现在就要改善这个死板的动作。

    其实我们可以将如此死板的动作理解为速度太快了,一瞬间就从50变到1000了,如果我们能让他先从50变成100,然后再变成150,最后变成1000,动作必然变得更加平滑,现在我让他同样时间内只变化少量px最终变成1000的时候,就停止。我可以用一个定时器来实现这一点。

    看我改善后的javascript部分的代码如下:

    var odiv1 = document.getElementsByTagName("div");
    window.onload = function(){
        var speed = 5;
        var timer = null;
        odiv1[0].onmouseover = function(){
            clearInterval(timer);
            timer = setInterval(function(){
                if(odiv1[0].offsetWidth == 1000){
                    clearInterval(timer);
                }
                else{
                    odiv1[0].style.width = odiv1[0].offsetWidth+speed+"px";
                }
            },30)
        }
        odiv1[0].onmouseout = function(){
            clearInterval(timer);
            timer = setInterval(function(){
                if(odiv1[0].offsetWidth == 50){
                    clearInterval(timer);
                }
                else{
                    odiv1[0].style.width = (odiv1[0].offsetWidth-speed)+"px";
                }
            },30)
        }
    }

    现在我们看到了一个非常平滑的动画,并且speed可以移动,虽然这样的动画效果已经让你感觉很满意了,但是,他依然不够美观,这是一个匀速运动,我们喜欢看到的是一种缓冲运动,现在我们在speed上下文章,把speed定义为距离目标越近则越小,可以实现缓冲运动。代码改善如下:

    var odiv1 = document.getElementsByTagName("div");
    window.onload = function(){
        var timer = null;
        odiv1[0].onmouseover = function(){
            clearInterval(timer);
            timer = setInterval(function(){
                var speed = (1000-odiv1[0].offsetWidth)/8;
                if(odiv1[0].offsetWidth == 1000){
                    clearInterval(timer);
                }
                else{
                    odiv1[0].style.width = odiv1[0].offsetWidth+speed+"px";
                }
            },30)
        }
        odiv1[0].onmouseout = function(){
            clearInterval(timer);
            timer = setInterval(function(){
                var speed = (odiv1[0].offsetWidth-50)/8;
                if(odiv1[0].offsetWidth == 50){
                    clearInterval(timer);
                }
                else{
                    odiv1[0].style.width = (odiv1[0].offsetWidth-speed)+"px";
                }
            },30)
        }
    }

    这时候看到的就是变速运动了,这里面还存在两个小问题,首先是,代码几乎没有重用性,我们在两个事件中的代码几乎相同,所以可以封装为同一段代码。其次,speed存在小数行为,小数是我们无法容忍的,不解释……下面继续对代码进行改进。

    首先,我们需要对相同代码进行封装,我们现在把目标改为不确定,也就是说我们把div想要变成多大作为参数传进函数中,既能增加div长度也能减少,同时当鼠标移开的时候div恢复原来长度。下面看封装的代码:

    window.onload = function(){
        var timer = null;
        function startMove(target){
            clearInterval(timer);
            timer = setInterval(function(){
                var speed = (target-odiv1[0].offsetWidth)/8;
                if(odiv1[0].offsetWidth == target){
                    clearInterval(timer);
                }
                else{
                    odiv1[0].style.width = odiv1[0].offsetWidth+speed+"px";
                }
            },30)
        }
        var odiv1 = document.getElementsByTagName("div");
        odiv1[0].onmouseover = function(){
            startMove(20);
        }
        odiv1[0].onmouseout = function(){
            startMove(50);
        }
    }

    这段代码封装了startMove()函数,看到效果完全跟原来相同。

    下面我们来解决小数的问题:

    我们可以利用javascript的Math对象的方法将小数转换为整数,具体如何转换不再赘述,下面是我改善的代码:

    window.onload = function(){
        var timer = null;
        function startMove(target){
            clearInterval(timer);
            timer = setInterval(function(){
                var speed = (target-odiv1[0].offsetWidth)/8;
                if(speed>0){
                    speed=Math.ceil(speed);
                }
                else{
                    speed=Math.floor(speed);
                }
                if(odiv1[0].offsetWidth == target){
                    clearInterval(timer);
                }
                else{
                    odiv1[0].style.width = odiv1[0].offsetWidth+speed+"px";
                }
            },30)
        }
        var odiv1 = document.getElementsByTagName("div");
        odiv1[0].onmouseover = function(){
            startMove(20);
        }
        odiv1[0].onmouseout = function(){
            startMove(50);
        }
    }

    现在运动框架基本成型,最后我们需要的不仅仅是对一个对象进行运动,我们有时候一个页面需要很多元素需要动画,这时候我们需要对函数进行进一步封装,把运动的对象也放进函数中进行封装。

    下面是代码:

        function startMove(obj,target){
            clearInterval(obj.timer);
            obj.timer = setInterval(function(){
                var speed = (target-obj.offsetWidth)/8;
                if(speed>0){
                    speed=Math.ceil(speed);
                }
                else{
                    speed=Math.floor(speed);
                }
                if(obj.offsetWidth == target){
                    clearInterval(obj.timer);
                }
                else{
                    obj.style.width = obj.offsetWidth+speed+"px";
                }
            },30)
        }
        window.onload = function(){
            var odiv1 = document.getElementsByTagName("div");
            for(var i=0;i<odiv1.length;i++){
                odiv1[i].timer = null;
                odiv1[i].onmouseover = function(){
                    startMove(this,200);
                }
                odiv1[i].onmouseout = function(){
                    startMove(this,50);
                }
            }
        }

    就这样我们建立了一个简单的运动框架实现了动画效果。并且代码具有一定的重用性。

  • 相关阅读:
    EventBridge消息路由|高效构建消息路由能力
    技术盘点:消息中间件的过去、现在和未来
    峰会报名|从金融行业技术选型,看 RocketMQ 如何应对严苛挑战
    从旁观者到贡献者:经历 OpenYurt 的“开源之夏”,我们想让更多人体验社区的魅力
    如虎添翼!高德地图+Serverless 护航你的假日出行
    关于阿里云多活容灾的那点事
    在阿里巴巴,我们如何先于用户发现和定位 Kubernetes 集群问题?
    直播带练 | 30 分钟用阿里云容器服务和容器网络文件系统搭建 WordPress 网站
    阿里巴巴副总裁陈丽娟:我对阿里云产品生态的思考 | 云原生加速器观点
    重新理解“无容灾不上云”:应用多活将成为云原生容灾新趋势
  • 原文地址:https://www.cnblogs.com/bianbiangege/p/3423683.html
Copyright © 2020-2023  润新知