怎么解决鼠标移入移除,图片无法迅速切换过来的问题

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    *{
        margin: 0;
        padding: 0;
    }

    ul,li{
        list-style: none;
    }

    .imglist {
        width: 1000px;
        height: 400px;
    }
    .imglist ul {
        width: 1000px;
        overflow: hidden;
    }
    .imglist ul li.item {
        width: 200px;
        height: 400px;

        float: left;

        opacity: 0.3;
        filter: alpha(opacity=30);
    }

    .imglist ul li.item img {
        width: 200px;
        height: 400px;

        float: left;
    }
  </style>
</head>
<body>
<div class="imglist">
    <ul id="imglist">
        <li class="item i1"><img src="1.jpg" alt=""></li>
        <li class="item i2"><img src="1.jpg" alt=""></li>
        <li class="item i3"><img src="1.jpg" alt=""></li>
        <li class="item i4"><img src="1.jpg" alt=""></li>
        <li class="item i5"><img src="1.jpg" alt=""></li>
    </ul>
</div>
<script>

window.onload = function () {
    var oImg = document.getElementById('imglist');
    var oImgLi = oImg.getElementsByTagName('li');
    var alpha = 0.3;
    var i=0;
    var timer = null;
    var flag = true;
    
    for(len=oImgLi.length;i<len;i++){
        oImgLi[i].onmouseover = function () {
            startMove(this,1);
         
        };

        oImgLi[i].onmouseout = function () {
            startMove(this,0.3);
        };
    }

    function startMove (obj, iTarget) {
        clearInterval(timer);
        timer = setInterval(function(){
            var speed = 0;
            if( alpha < iTarget ) {
                speed = 0.1;
            }else{
                speed = -0.1;
            }

            if(alpha === iTarget){
                clearInterval(timer);
            }else{
                alpha = (alpha*10 + speed*10)/10;
                obj.style.opacity = alpha;
                obj.style.filter = "alpha(opacity="+ alpha*100 +")";
            }
        },30);
    }
 };

</script>
</body>
</html>
阅读 2.1k
1 个回答

代码啥的无大碍,就是变量作用域没有分离开,简单的说在你的循环里打个闭包(构建新的作用域)就可以了。

主要问题在于每个li动画的状态都是不可共享的,每个li有自己的timer时间alpha透明度,如果每个动画状态被共享(就是题主之前的代码),就会出现以下这种情况:

  1. 鼠标移入第一张图片a,执行startMovesetInterval开始根据间隔反复执行。

  2. 比如第一张图片alpha透明度执行到了0.7的时候,移动鼠标到了第二张图片:

    1. 第一张图片执行onmouseout,执行startMove(this, 0.3),但是它是一个异步任务,所以被挂到event loop,在300ms之后执行(关于event loop以及它的异步流程请参考我的这边文章:《JavaScript下的setTimeout(fn,0)意味着什么?》)。

    2. 接着第二张图片的也执行了startMove,但是它的alphatimer都是第一张图片的状态,此时它直接清空了timer,造成的结果就是第一张图片被挂起的300ms任务被clear掉了。

  3. 接着题主就看到了bug现象:第二张发生了动画opacity=1,但是第一张图片opacity也是1

具体修正的代码如下,只需要把共享的变量alpha & timer放到闭包里即可:

var oImg = document.getElementById('imglist');
var oImgLi = oImg.getElementsByTagName('li');
//ES5的func
Array.prototype.forEach.call(oImgLi, function (img) {//传递回调函数,构建新的作用域
    //timer、alpha和startMove,不应该被每个li共享使用,因为每个li都有自己的状态,自己的动画状态(自己的动画时长,alpha透明度)
    var timer = null,
        alpha = 0.3;
    function startMove(obj, iTarget) {
        clearInterval(timer);
        timer = setInterval(function () {
            var speed = 0;
            if (alpha < iTarget) {
                speed = 0.1;
            } else {
                speed = -0.1;
            }

            if (alpha === iTarget) {
                clearInterval(timer);
            } else {
                alpha = (alpha * 10 + speed * 10) / 10;
                obj.style.opacity = alpha;
                obj.style.filter = "alpha(opacity=" + alpha * 100 + ")";
            }
        }, 30);
    }
    img.onmouseover = function () {
        startMove(this, 1);

    };

    img.onmouseout = function () {
        startMove(this, 0.3);
    };
});

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题