【JavaScript从入门到精通】第十九课 JS运动中级

此内容来自开课吧石川微信公众号

前面的学习已经让我们掌握了很多运动相关的知识,也构造出了自己的运动框架,当然,它离真正的完成版运动框架还有很远的距离。

链式运动框架

在我们讲解链式运动框架时,我们需要讲解一下什么是回调函数。在我们之前的一个运动函数startMove中,如果我们再添加一个参数,而且该参数是一个函数,我们希望在运动结束后调用这个函数——这就是所谓的回调函数。

function startMove(obj, attr, iTarget, fnEnd){
    clearInterval(obj.timer);
    obj.timer=setInterval(function (){
        var cur=0;
        if(attr=='opacity')
        {
            cur=Math.round(parseFloat(getStyle(obj, attr))*100);
        }
        else
        {
            cur=parseInt(getStyle(obj, attr));
        }

        var speed=(iTarget-cur)/6;
        speed=speed>0?Math.ceil(speed):Math.floor(speed);

        if(cur==iTarget)
        {
            clearInterval(obj.timer);

            if(fnEnd)fnEnd();
        }
        else
        {
            if(attr=='opacity')
            {
                obj.style.filter='alpha(opacity:'+(cur+speed)+')';
                obj.style.opacity=(cur+speed)/100;
            }
            else
            {
                obj.style[attr]=cur+speed+'px';
            }
        }
    }, 30);};

在clearInterval之后,我们调用这个函数(当然这里需要判断一下函数是否被传入)。

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>无标题文档</title>
    <script src="move.js"></script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
#div1 {
    width: 100px;
    height: 100px;
    background: red;
    filter: alpha(opacity:30);
    opacity: 0.3;
}
window.onload = function () {
    var oDiv = document.getElementById('div1');

    oDiv.onmouseover = function () {
        startMove(oDiv, 'width', 300, function () {
            startMove(oDiv, 'height', 300, function () {
                startMove(oDiv, 'opacity', 100);
            });
        });
    };

    oDiv.onmouseout = function () {
        startMove(oDiv, 'opacity', 30, function () {
            startMove(oDiv, 'height', 100, function () {
                startMove(oDiv, 'width', 100);
            });
        });
    };
};

效果如下:

【JavaScript从入门到精通】第十九课 JS运动中级

可以看到,我们通过回调函数的嵌套实现了一个比较炫酷的伸缩展开效果——这就是一个简单的链式运动框架。

完美运动框架

到目前为止,我们学习的运动框架依然是有问题存在的:

<html>
<head>
    <meta charset="utf-8">
    <title>无标题文档</title>
    <script src="move.js"></script>
</head>
<body>
<input id="btn1" type="button" value="运动"/>
<div id="div1"></div>
</body>
</html>
#div1 {
    width: 100px;
    height: 100px;
    background: red;
}
window.onload = function () {
    var oBtn = document.getElementById('btn1');
    var oDiv = document.getElementById('div1');

    oBtn.onclick = function () {
        startMove(oDiv, 'width', 300);
        startMove(oDiv, 'height', 300);
    };
};

效果如下:

【JavaScript从入门到精通】第十九课 JS运动中级

可以看到,我们试图让div的宽和高同时变化,但结果而言只有高度发生了变化,原因在于两次调用函数的定时器产生了干扰,因此只有后一个startmove函数生效了。那么,我们现在的运动框架无法使好几个属性同时发生变化,应该怎么解决它呢?答案是通过json,json有一个重要用法是循环——使用for in方法进行。我们之前传入属性和属性值是通过两个参数进行的,现在我们直接传入一个json,将属性和属性值分别作为键名和键值传入,这样我们就可以同时传入好几组值了。

function startMove(obj, json, fnEnd) {
    clearInterval(obj.timer);
    obj.timer = setInterval(function () {
        var bStop = true;     //假设:所有值都已经到了
        for (var attr in json) {
            var cur = 0;
            if (attr == 'opacity') {
                cur = Math.round(parseFloat(getStyle(obj, attr)) * 100);
            }
            else {
                cur = parseInt(getStyle(obj, attr));
            }
            var speed = (json[attr] - cur) / 6;
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
            if (cur != json[attr])
                bStop = false;
            if (attr == 'opacity') {
                obj.style.filter = 'alpha(opacity:' + (cur + speed) + ')';
                obj.style.opacity = (cur + speed) / 100;
            }
            else {
                obj.style[attr] = cur + speed + 'px';
            }
        }
        if (bStop) {
            clearInterval(obj.timer);
            if (fnEnd) fnEnd();
        }
    }, 30);
}

通过json键值对和for in循环,我们就可以同时改变一个元素的好几个属性了。这里注意一点,原本的运动框架当属性值等于目标值时,运动就会停下来,但同时运动的时候几个运动结束的时间并不是一样的——我们应该等所有运动都结束之后再关闭定时器,因此我们建立了一个bStop变量来判断是否所有运动都到达了终点。

<html>
<head>
    <meta charset="utf-8">
    <title>无标题文档</title>
    <script src="move2.js"></script>
</head>
<body>
<input id="btn1" type="button" value="运动"/>
<div id="div1"></div>
</body>
</html>
#div1 {
    width: 100px;
    height: 100px;
    background: red;
    filter: alpha(opacity:30);
    opacity: 0.3;
}
window.onload = function () {
    var oBtn = document.getElementById('btn1');
    var oDiv = document.getElementById('div1');

    oBtn.onclick = function () {
        startMove(oDiv, {width: 101, height: 300, opacity: 100}, function () {
            alert('a');
        });
    };
};

效果如下:

【JavaScript从入门到精通】第十九课 JS运动中级

这样,这个框架既可以同时改变元素的不同属性值(通过json实现),也可以分阶段进行属性值改变(通过回调函数实现),就形成了一个比较完美的运动框架,在css2范围内,这个运动框架已经足够使用了。

到这里我们的运动框架基本就已经讲解结束了,这里为大家总结一下我们编写过的运动框架:

  • startMove(iTarget) 运动框架
  • startMove(obj, iTarget) 多物体
  • startMove(obj, attr, iTarget) 任意值
  • startMove(obj, attr, iTarget, fn) 链式运动
  • startMove(obj, json) 多值运动
  • startMove(obj, json, fn) 完美运动框架

如需转载,烦请注明出处:https://www.qdskill.com/javascript/559.html

发表评论

登录后才能评论