发新贴  快速回复

多个li宽高变化,一段时间的自运行后,li回不到原有宽高

XCN
2013-05-07 15:46
[html]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<style>
#banner {width:964px;height:323px;overflow:hidden;position:relative;margin:0 auto;}
#banner ul {z-index:1;width:964px;overflow:hidden;height:323px;position:relative;padding:0;margin:0;}
#banner li {position:absolute;display:block;left:0;top:0;height:323px;width:964px;z-index:1;overflow:hidden}
#banner img{border:0;width:964px;height:323px;}
#banner dl {position:absolute;z-index:10000;bottom:3px;right:3px;margin:0;}
#banner dd {width:22px;height:22px;/*background-position:-1% 101%;*/background:#ccc;float:left;margin:0 2px;cursor:pointer;text-align:center;line-height:22px;}
#banner dd.on {/*    background-position:0 82%;*/background:red}
</style>

<script>
function css(obj,attr,value){
    if(arguments.length==2){
        if(typeof attr!='object'){
            if(attr!='opacity'){
                return parseInt(obj.currentStyle?obj.currentStyle[attr]:document.defaultView.getComputedStyle(obj,false)[attr])
            }else{
                return Math.round(100*parseFloat(obj.currentStyle?obj.currentStyle[attr]:document.defaultView.getComputedStyle(obj,false)[attr]))
            }
        }else{
            for(key in attr){
                switch(key){
                    case 'opacity':
                                   obj.style[key]=value/100;
                                   obj.style.filter='alpha(opacity:'+value+')';
                                   break;
                    case 'width':
                    case 'height':
                    case 'paddingTop':
                    case 'paddingBottom':
                    case 'paddingLeft':
                    case 'paddingRight':
                                         attr[key]=Math.max(0,attr[key]);
                    case 'left':
                    case 'top':
                    case 'bottom':
                    case 'right':
                    case 'marginLeft':
                    case 'marginTop':
                    case 'marginRight':
                    case 'marginBottom':
                                         obj.style[key]=attr[key]+'px';
                                         break;
                    default:
                            obj.style[key]=attr[key];
                            break;
                }                
            }
        }
    }else if(arguments.length==3){
        switch(attr){
            case 'opacity':
                           obj.style[attr]=value/100;
                           obj.style.filter='alpha(opacity:'+value+')';
                           break;
            case 'width':
            case 'height':
            case 'paddingTop':
            case 'paddingBottom':
            case 'paddingLeft':
            case 'paddingRight':
                                 value=Math.max(0,value);
            case 'left':
            case 'top':
            case 'bottom':
            case 'right':
            case 'marginLeft':
            case 'marginTop':
            case 'marginRight':
            case 'marginBottom':
                                 obj.style[attr]=value+'px';
                                 break;
            default:
                    obj.style[attr]=value;
                    break;
        }
    }
}
function startMove(obj,oTarget,iType,fn){
    if(obj.timer){clearInterval(obj.timer)};
    var fnMove=null;
    switch(iType){
        case 1:
               fnMove=DoMoveBuffer;
               break;
        case 2:
               fnMove=DoMoveFlex;
               break;
        default:
                fnMove=null;
                break;
    }
    obj.timer=setInterval(function(){fnMove(obj,oTarget,fn)},30)
}
function DoMoveBuffer(obj,oTarget,fn){
    var bStop=true,attr='',iSpeed=0,iCur=0;
    for(attr in oTarget){
        iCur=css(obj,attr);
        iSpeed=(oTarget[attr]-iCur)/8;
        iSpeed=iSpeed>0?Math.ceil(iSpeed):Math.floor(iSpeed);
        if(iCur!=oTarget[attr]){    
            bStop=false;
            css(obj,attr,iCur+iSpeed);
        }
    }
    if(bStop){
        clearInterval(obj.timer);
        obj.timer=null;
        if(fn){fn()};
    }
}
function DoMoveFlex(obj,oTarget,fn){}
window.onload=function(){
    var oDiv=document.getElementById('banner');
    var oOl=oDiv.getElementsByTagName('dl')[0];
    var oUl=oDiv.getElementsByTagName('ul')[0];
    var aLiBtn=oOl.getElementsByTagName('dd');
    var aLiAds=oUl.getElementsByTagName('li');
    var iMinZindex=2,iNow=0,n=0,iCur=0,Autotimer=null;
    var temp=[{height:0},{width:0},{height:0,width:0},{height:0,top:323},{width:0,left:964},{width:0,height:0,left:964,top:323},{width:0,height:0,left:482,top:162}]
    
    for(var i=0;i<aLiBtn.length;i++){
        aLiBtn[i].index=i;
        aLiBtn[i].onclick=function(){
            if(iNow==this.index)return;
            iCur=iNow=this.index;
            n=parseInt(temp.length*Math.random());
            tabChange(n);
        }
    }
    aLiAds[0].onmouseover=function(){clearInterval(Autotimer)};
    aLiAds[0].onmouseout=function(){Autotimer=setInterval(autoPlay,3000)};    
    oOl.onmouseover=function(){clearInterval(Autotimer)};
    oOl.onmouseout=function(){Autotimer=setInterval(autoPlay,3000)};        
    function tabChange(n){
        aLiAds[iNow].onmouseover=function(){clearInterval(Autotimer)};
        aLiAds[iNow].onmouseout=function(){Autotimer=setInterval(autoPlay,3000)};
        for(var j=0;j<aLiBtn.length;j++){aLiBtn[j].className=''};
        document.title=iNow;
        aLiBtn[iNow].className='on';
        css(aLiAds[iNow],'zIndex',iMinZindex++);
        if(n==0){
            css(aLiAds[iNow],{height:0});
            startMove(aLiAds[iNow],{height:323},1)
        };
        if(n==1){
            css(aLiAds[iNow],{width:0});
            startMove(aLiAds[iNow],{width:964},1)
        }
        if(n==2){
            css(aLiAds[iNow],{width:0,height:0});
            startMove(aLiAds[iNow],{width:964,height:323},1)
        }
        if(n==3){
            css(aLiAds[iNow],{height:0,top:323});
            startMove(aLiAds[iNow],{height:323,top:0},1)
        }
        if(n==4){
            css(aLiAds[iNow],{width:0,left:964});
            startMove(aLiAds[iNow],{width:964,left:0},1)
        }
        if(n==5){
            css(aLiAds[iNow],{width:0,height:0,left:964,top:323});
            startMove(aLiAds[iNow],{width:964,height:323,left:0,top:0},1)
        }
        if(n==6){
            css(aLiAds[iNow],{width:0,height:0,left:482,top:162});
            startMove(aLiAds[iNow],{width:964,height:323,left:0,top:0},1)
        }
    }
    function autoPlay(){
        iCur++;
        if(iCur<aLiBtn.length){
            iNow=iCur;
        }else if(iCur>=aLiBtn.length&&iCur<2*aLiBtn.length-1){
            iNow=2*aLiBtn.length-iCur-2;
        }
        else if(iCur>=aLiBtn.length-1){
            iNow=iCur=1;
        }
        n=parseInt(temp.length*Math.random());
        tabChange(n);
    }
    Autotimer=setInterval(autoPlay,3000);
}
    </script>
</head>

<body>
    <div id="banner">
        <ul>
          <li style="z-index:2; background:#000"></li>
          <li style=" background:#333"></li>
          <li style="background:#666"></li>
          <li style="background:#999"></li>
          <li style="background:#CCC"></li>
          <li style="background:#99F"></li>
        </ul>
        <dl>
            <dd class="on" style="color:#000">1</dd>
            <dd style="color:#333">2</dd>
            <dd style="color:#666">3</dd>
            <dd style="color:#999">4</dd>
            <dd style="color:#ccc">5</dd>
            <dd style="color:#99f">6</dd>
        </dl>
    </div>
</body>
</html>
[/html]
XCN
问题:当多个li首次运行后,能运行自如,回到正常宽高,可是当运行一段时间后会出现运行失常,回不到正常宽高而进行下一次运动
2013-05-07 15:49  回复本帖
XCN
请问妙味的JS大咔给小弟解解惑,感谢
2013-05-07 15:50  回复本帖
ghostdp
尽量不要让定时器多长时间的运作~

function autoPlay(){
                iCur++;
                if(iCur<aLiBtn.length){
                        iNow=iCur;
                }else if(iCur>=aLiBtn.length&&iCur<2*aLiBtn.length-1){
                        iNow=2*aLiBtn.length-iCur-2;
                }
                else if(iCur>=aLiBtn.length-1){
                        iNow=iCur=1;
                }
                n=parseInt(temp.length*Math.random());
                tabChange(n);
                clearInterval(Autotimer);
                Autotimer=setInterval(autoPlay,3000);
        }
2013-05-07 17:15  回复本帖
XCN
ghostdp 发表于 2013-5-7 17:15 forum.php?mod=redirect&goto=findpost&pid=19269&ptid=6744
尽量不要让定时器多长时间的运作~

function autoPlay(){


会因定时器长时间运动而出现运动效果乱象么?这其中有什么解释?
2013-05-07 21:22  回复本帖
XCN
ghostdp 发表于 2013-5-7 17:15 forum.php?mod=redirect&goto=findpost&pid=19269&ptid=6744
尽量不要让定时器多长时间的运作~

function autoPlay(){


嗯,合理的控制好定时器开关很重要,但是还是会出现我说的问题:那就是你一段时间不切换该窗口,关注这个效果是ok的,但是切换窗口一会,再切换回来还是出现乱象,那个宽高没有按照指定位置变化,而且乱象也只是一两个来回的轮显(当然这段时间内没有切换窗口),然后又恢复了正常,还请解惑啊
2013-05-07 21:32  回复本帖
无为
这是浏览器自身优化设计导致的问题,绝大部分浏览器为了提高浏览器的性能,当窗口失去焦点(即在标签浏览模式下,切换到另一个标签页上)的时候,会把这个窗口中的定时器等一些持续执行的代码和占用内存比较大的代码的执行放慢,有一些计算可能也会暂时停止。  

你的这个问题就是因为浏览器自身的优化处理导致的上一次运动还没结束,下一个定时器就开始执行了。你可以观察在切换到其它窗口的时候, 输出到title中的数字的变化时间间隔,比你设置的3000毫秒要长。


解决这个问题的办法是不用setInterval定时器,而使用setTimeout定时器,这样可以保证上一次运动结束了才进行下一次运动。

修改后的代码如下,因为你的autoplay函数每次都要调用toChange函数,所以我合并成一个函数了:<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<style>
#banner {width:964px;height:323px;overflow:hidden;position:relative;margin:0 auto;}
#banner ul {z-index:1;width:964px;overflow:hidden;height:323px;position:relative;padding:0;margin:0;}
#banner li {position:absolute;display:block;left:0;top:0;height:323px;width:964px;z-index:1;overflow:hidden}
#banner img{border:0;width:964px;height:323px;}
#banner dl {position:absolute;z-index:10000;bottom:3px;right:3px;margin:0;}
#banner dd {width:22px;height:22px;/*background-position:-1% 101%;*/background:#ccc;float:left;margin:0 2px;cursor:pointer;text-align:center;line-height:22px;}
#banner dd.on {/*    background-position:0 82%;*/background:red}
</style>

<script>
function css(obj,attr,value){
    if(arguments.length==2){
        if(typeof attr!='object'){
            if(attr!='opacity'){
                return parseInt(obj.currentStyle?obj.currentStyle[attr]:document.defaultView.getComputedStyle(obj,false)[attr])
            }else{
                return Math.round(100*parseFloat(obj.currentStyle?obj.currentStyle[attr]:document.defaultView.getComputedStyle(obj,false)[attr]))
            }
        }else{
            for(key in attr){
                switch(key){
                    case 'opacity':
                        obj.style[key]=value/100;
                        obj.style.filter='alpha(opacity:'+value+')';
                        break;
                    case 'width':
                    case 'height':
                    case 'paddingTop':
                    case 'paddingBottom':
                    case 'paddingLeft':
                    case 'paddingRight':
                        attr[key]=Math.max(0,attr[key]);
                    case 'left':
                    case 'top':
                    case 'bottom':
                    case 'right':
                    case 'marginLeft':
                    case 'marginTop':
                    case 'marginRight':
                    case 'marginBottom':
                        obj.style[key]=attr[key]+'px';
                        break;
                    default:
                        obj.style[key]=attr[key];
                        break;
                }                
            }
        }
    }else if(arguments.length==3){
        switch(attr){
            case 'opacity':
                obj.style[attr]=value/100;
                obj.style.filter='alpha(opacity:'+value+')';
                break;
            case 'width':
            case 'height':
            case 'paddingTop':
            case 'paddingBottom':
            case 'paddingLeft':
            case 'paddingRight':
                value=Math.max(0,value);
            case 'left':
            case 'top':
            case 'bottom':
            case 'right':
            case 'marginLeft':
            case 'marginTop':
            case 'marginRight':
            case 'marginBottom':
                obj.style[attr]=value+'px';
                break;
            default:
                obj.style[attr]=value;
                break;
        }
    }
}

function startMove(obj,oTarget,iType,fn){
    if(obj.timer){clearInterval(obj.timer)};
    var fnMove=null;
    switch(iType){
        case 1:
            fnMove=DoMoveBuffer;
            break;
        case 2:
            fnMove=DoMoveFlex;
            break;
        default:
            fnMove=null;
            break;
    }
    obj.timer=setInterval(function(){fnMove(obj,oTarget,fn)},30)
}

function DoMoveBuffer(obj,oTarget,fn){
    var bStop=true,attr='',iSpeed=0,iCur=0;
    for(attr in oTarget){
        iCur=css(obj,attr);
        iSpeed=(oTarget[attr]-iCur)/8;
        iSpeed=iSpeed>0?Math.ceil(iSpeed):Math.floor(iSpeed);
        if(iCur!=oTarget[attr]){    
            bStop=false;
            css(obj,attr,iCur+iSpeed);
        }
    }
    if(bStop){
        clearInterval(obj.timer);
        obj.timer=null;
        if(fn){fn()};
    }
}

function DoMoveFlex(obj,oTarget,fn){}

window.onload=function(){
    var oDiv=document.getElementById('banner');
    var oOl=oDiv.getElementsByTagName('dl')[0];
    var oUl=oDiv.getElementsByTagName('ul')[0];
    var aLiBtn=oOl.getElementsByTagName('dd');
    var aLiAds=oUl.getElementsByTagName('li');
    var iMinZindex=2,iNow=0,n=0,iCur=0,Autotimer=null;
    var temp=[{height:0},{width:0},{height:0,width:0},{height:0,top:323},{width:0,left:964},{width:0,height:0,left:964,top:323},{width:0,height:0,left:482,top:162}]
    
    for(var i=0;i<aLiBtn.length;i++){
            aLiBtn[i].index=i;
            aLiBtn[i].onclick=function(){
                    if(iNow==this.index)return;
                    iCur=iNow=this.index;
                    n=parseInt(temp.length*Math.random());
                    tabChange(n);
            }
    }
    aLiAds[0].onmouseover=function(){clearTimeout(Autotimer)};
    aLiAds[0].onmouseout=function(){clearTimeout(Autotimer);Autotimer=setTimeout(tabChange,3000);};    
    oOl.onmouseover=function(){clearTimeout(Autotimer)};
    oOl.onmouseout=function(){clearTimeout(Autotimer);Autotimer=setTimeout(tabChange,3000);}; 
    
    function tabChange(n){
            iCur++;
            if(iCur<aLiBtn.length){
                    iNow=iCur;
            }else if(iCur>=aLiBtn.length&&iCur<2*aLiBtn.length-1){
                    iNow=2*aLiBtn.length-iCur-2;
            }
            else if(iCur>=aLiBtn.length-1){
                    iNow=iCur=1;
            }
            n=parseInt(temp.length*Math.random());

            aLiAds[iNow].onmouseover=function(){clearTimeout(Autotimer)};
            aLiAds[iNow].onmouseout=function(){clearTimeout(Autotimer);Autotimer=setTimeout(tabChange,3000);};
            for(var j=0;j<aLiBtn.length;j++){aLiBtn[j].className=''};
            document.title=iNow;
            aLiBtn[iNow].className='on';
            css(aLiAds[iNow],'zIndex',iMinZindex++);
            if(n==0){
                    css(aLiAds[iNow],{height:0});
                    startMove(aLiAds[iNow],{height:323},1,function(){
                        Autotimer=setTimeout(tabChange,3000);
                    })
            };
            if(n==1){
                    css(aLiAds[iNow],{width:0});
                    startMove(aLiAds[iNow],{width:964},1,function(){
                        Autotimer=setTimeout(tabChange,3000);
                    })
            }
            if(n==2){
                    css(aLiAds[iNow],{width:0,height:0});
                    startMove(aLiAds[iNow],{width:964,height:323},1,function(){
                        Autotimer=setTimeout(tabChange,3000);
                    })
            }
            if(n==3){
                    css(aLiAds[iNow],{height:0,top:323});
                    startMove(aLiAds[iNow],{height:323,top:0},1,function(){
                        Autotimer=setTimeout(tabChange,3000);
                    })
            }
            if(n==4){
                    css(aLiAds[iNow],{width:0,left:964});
                    startMove(aLiAds[iNow],{width:964,left:0},1,function(){
                        Autotimer=setTimeout(tabChange,3000);
                    })
            }
            if(n==5){
                    css(aLiAds[iNow],{width:0,height:0,left:964,top:323});
                    startMove(aLiAds[iNow],{width:964,height:323,left:0,top:0},1,function(){
                        Autotimer=setTimeout(tabChange,3000);
                    })
            }
            if(n==6){
                    css(aLiAds[iNow],{width:0,height:0,left:482,top:162});
                    startMove(aLiAds[iNow],{width:964,height:323,left:0,top:0},1,function(){
                        Autotimer=setTimeout(tabChange,3000);
                    })
            }
    }

    Autotimer=setTimeout(tabChange,3000);

}
  </script>
</head>

<body>
  <div id="banner">
  <ul>
    <li style="z-index:2; background:#000"></li>
    <li style=" background:#333"></li>
    <li style="background:#666"></li>
    <li style="background:#999"></li>
    <li style="background:#CCC"></li>
    <li style="background:#99F"></li>
  </ul>
  <dl>
    <dd class="on" style="color:#000">1</dd>
    <dd style="color:#333">2</dd>
    <dd style="color:#666">3</dd>
    <dd style="color:#999">4</dd>
    <dd style="color:#ccc">5</dd>
    <dd style="color:#99f">6</dd>
  </dl>
  </div>
</body>
</html>另外,  当运动还没结束的时候如果进行移入移出操作是有bug的,这是因为上一个定时器还没结束就又执行了另一个定时器,解决思路是如果运动还没有结束移入移出就不做任何运动,你可以先自己解决试试。
2013-05-08 18:32  回复本帖
XCN
无为 发表于 2013-5-8 18:32 forum.php?mod=redirect&goto=findpost&pid=19287&ptid=6744
这是浏览器自身优化设计导致的问题,绝大部分浏览器为了提高浏览器的性能,当窗口失去焦点(即在标签浏览模 ...

首先,很感谢管理员的答复,谢了啊!{:soso_e100:} 

看了下管理员的修改后的代码,未运行前有个小疑问:

如果合并两函数后,我点击下方某个数字时,要求是显示与其对应的大的 li 

可是经这么一改后,变成了点击小数字,iCur=iNow=this.index后运行tabChange()函数,里面又再次给iNow重赋值,造成直接结果是点击当前的数字,对应到下一个 li 变化了;

接着就是自动运行后会一次性执行三次运动,这个惊讶到我了。

最后,还是感谢管理员百忙中予以答复,感谢感谢,这个问题我得继续取经了
2013-05-08 21:57  回复本帖
XCN
无为 发表于 2013-5-8 18:32 forum.php?mod=redirect&goto=findpost&pid=19287&ptid=6744
这是浏览器自身优化设计导致的问题,绝大部分浏览器为了提高浏览器的性能,当窗口失去焦点(即在标签浏览模 ...

移入的话是clear掉定时器,移出是开启一个定时器,是有这么个矛盾在里面,正如你说的上个定时器还没运行结束就mouseover事件clear掉定时器,然后再out开启新的定时器,

个人这个好像不冲突;因为out必发生在over基础上,所以一旦开启新的定时器,上一个定时器已经清掉;

不过就存在这样的疑问:如果上个定时器没有运行完整就清掉了,可能会导致li没有达到指定宽高就清除了定时器,这样下次开启定时器时,可能会遇到这个没有到达指定宽高的li

但这个 li 会被css()函数指定的值重定义宽高后再出发完成startMove的宽高变化,最终还是会达到startMove指定的终点(也即是指定宽高)

不知道管理员怎么认为的??
2013-05-08 22:36  回复本帖
无为
XCN 发表于 2013-5-8 22:36 forum.php?mod=redirect&goto=findpost&pid=19295&ptid=6744
移入的话是clear掉定时器,移出是开启一个定时器,是有这么个矛盾在里面,正如你说的上个定时器还没运行 ...

注意你那个 Autotimer 变量,它一次只能存一个定时器,如果你在上一次运动结束之前再次触发的话,Autotimer会再存第二个定时器,这样的话,第一个定时器就没有变量名来对应,也就没有办法清除这个定时器了,所以会导致同时有两个或者多个定时器同时执行的情况。
2013-05-08 22:40  回复本帖
登录 后才可以发表回复