jQuery中处理动画序列引起的问题

jQuery中的动画效果应该是相当出色的,让我们能够以非常简单的代码来实现很多复杂的效果,比如show()、hide()、slideDown()、slideUp()等。另外,如果给同一个元素指定不同的动画效果,那么这些动画效果是按照序列来执行的,比如如下这段代码:
$(document).ready(function(){
    $('#panel').css('opacity','0.5');
        $('#panel').click(function(){
            $(this).animate({
                left:'500px',
                height:'200px',
                opacity:'1'
            },3000).animate({
                top:'200px',
                width:'200px'
            },3000).css('border','5px solid blue');
        });
    });
});

代码先将#panel这个元素的透明度设置为0.5,之后元素会先向右移动500px、高度变为200px、透明度变为1,再然后元素会在第一段动画完成后,向下移动200px,并且高度变为200px。这两段动画其实就组成了一个动画序列,先执行第一段,然后执行第二段。

不过有时候,这种有动画序列却会引起一些问题,比如我想用jQuery中的slideDown()和slideUp()来制作有滑动效果的下拉菜单:鼠标悬浮于导航的时候菜单滑下,鼠标离开的时候菜单滑上,可是如果不作任何处理,把鼠标快速地在几个导航上快速滑入滑出,菜单节奏就会乱掉,上上下下像在跳舞一下。

解决方法一:在你的点击事件中加上一个判断

假设产生动画效果目标的是target,那么你要加上这个判断

<script type="text/javascript">
if(!target.is(":animated")){}
</script>
他会确保你的动画只会在上一个动画结束后才能产生 ,可以保持动画的完整性,但是连续点击时会有反映迟钝的感觉

解决方法二:使用jQuery带的stop()方法

jQuery自带的stop()方法的描述是这样的

stop( [clearQueue] [, gotoEnd] )两个参数均为可选,它们都是布尔值clearQueue表示是否清空未执行完的动画序列gotoEnd表示是否将正执行的动画跳转到末状态如果两个参数均不设置,则它会立即停止当前元素的动画。如果动画序列中还有其他的动画,则会以当前状态开始执行接下来的动画
那么想想这个菜单的实际情况:鼠标移入的时候,实际它就会在动画序列里添加一个slideDown动画,然后在鼠标移出的时候再添加一个slideUp动画。因为动画是按顺序执行的,所以第二个动画非得等到第一个动画执行完毕了以后再执行。如果鼠标移入移出的速度过快,动画就会慢慢按序列里的顺序执行直到完毕,所以就会出现DEMO1中的效果。那么用stop()的方法来清空序列不就行了?是的,所以把stop()方法的第一个参数设置为true。那第二个值呢?我们想想,我们的目标是把菜单完全展示于用户的面前,并且slideUp动画是需要基于之前slideDown的状态来完成的,你slideDown把菜单的整个高度都显示出来了,slideUp才好把菜单隐藏掉。另外还需要注意的一点是,slideUp和slideDown动画未执行完的时候,会把过程中的临时变量记录到DOM中,也就是说,如果你指定第二个参数为false,那么比如菜单高度有100px,但因为鼠标移出提前结束了,只展开了10px,那么菜单的高度就是10px并且被记录在DOM中了。再次使用slideDown的话,它就会以10px为基础展开,显然菜单并不会完整地展示于用户有面前。所以把第二个参数也设置为true,让它让元素动画直接跳转到末状态。大家可以把鼠标快速地在导航上滑入滑出试试看,虽然动画没有什么问题,但是能明显看到,如果在菜单展开的过程中移出了鼠标,菜单会立刻全部展开到末状态,而不是慢慢展开。关键代码如下
$(document).ready(function(){
    $('#menu > li').hover(function(){
        //这里的stop(true,true)指的是让动画队列清空,并且让已经在进行动画的元素到达动画的末状态,方便在第二次动画中使用
        $(this).find('ul').eq(0).stop(true,true).slideDown('slow');
    },function(){
        $(this).find('ul').eq(0).stop(true,true).slideUp('slow');
    });
});

解决方法三:使用setTimeout来判断鼠标悬停的时间

$(document).ready(function(){
    //设定两个数组,分别对应在不同元素上鼠标滑入和滑出要触发的函数
    //鼠标滑入的数组
    varmouseover_tid = [];
    //鼠标滑出的数组
    varmouseout_tid = [];
    //使用each()方法,index为此方法自动传入的参数,记录匹配元素在元素集合中的所处位置
    $('#menu > li').each(function(index){
        $(this).hover(function(){
            //this为当前的li元素,这里赋给self变量,方便在setTimeout方法中引用
            varself = this;
            //先清除鼠标滑出时的slideUp方法
            clearTimeout(mouseout_tid[index]);
            //鼠标滑入时,把当前的鼠标滑放的方法记录到数组中,并判断鼠标停留的时间是否符合条件
            mouseover_tid[index] = setTimeout(function(){
                //如果这里不用self而用this,this指向的就不是当前的li这个DOM元素
                $(self).find('ul').eq(0).slideDown('slow');
            },150);
        },function(){
            //鼠标滑出时的说明与滑入时的说明相似,此处省略
            varself = this;
            clearTimeout(mouseover_tid[index]);
            mouseout_tid[index] = setTimeout(function(){
                $(self).find('ul').eq(0).slideUp('slow');
            },150);
        });
    });
});


转载于:https://my.oschina.net/kangweb/blog/1635381

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值