完全圖解scrollLeft,scrollWidth,clientWidth,offsetWidth 獲取相對途徑,滾動圖片


有時候項目中會用到用js獲取元素位置來定位元素,我在網上開了大量的   圖解,代碼,最終把我搞的暈了,還是結合網上的 自己來總結一下,首先來看看網上的:

DOM的定義如下圖

 

獲取元素的位置屬性可以通過

  • HTMLElement.offsetLeft
  • HTMLElement.offsetTop

但是,這兩個屬性所儲存的數值並不是該元素相對整個瀏覽器畫布的絕對位置,而是相對於其父元素位置的相對位置,也就是說這兩個數值得到的是以其 父元素左上角為(0,0)點從而計算出的數值。所以我們要得到她的絕對位置,那么我們必須依次向上獲取他的父元素的位置,然后獲取它父元素的父元素的offersetLeft和offersetTop,一直遞歸到瀏覽器的整個畫布橫縱距離的時候,例如(  一定注意是相對於父標簽的途徑!) 

復制代碼
/*獲取元素的縱坐標*/
function getTop(e){
   
var offset=e.offsetTop;
   
if(e.offsetParent!=null){
     offset
+=getTop(e.offsetParent);
   }         
   
return offset;
}
/*獲取元素的橫坐標*/
function getLeft(e){
   
var offset=e.offsetLeft;
   
if(e.offsetParent!=null){
      offset
+=getLeft(e.offsetParent);
   } 
   
return offset;
復制代碼

 獲取元素的絕對位置,無非是根據元素距瀏覽器左邊(left)和頂部(top),我們可以稍稍改變一下得到一方法

復制代碼
function getElemPos(obj){
        
var pos = {"top":0"left":0};
         
if (obj.offsetParent){
           
while (obj.offsetParent){
             pos.top 
+= obj.offsetTop;
             pos.left 
+= obj.offsetLeft;
             obj 
= obj.offsetParent;
           }
         }
else if(obj.x){
           pos.left 
+= obj.x;
         }
else if(obj.x){
           pos.top 
+= obj.y;
         }
         
return {x:pos.left, y:pos.top};
}
復制代碼

 

 

 

 

 

 

 

scrollLeft:設置或獲取位於對象左邊界和窗口中目前可見內容的最左端之間的距離
scrollTop:設置或獲取位於對象最頂端和窗口中可見內容的最頂端之間的距離
scrollWidth:獲取對象的滾動寬度
offsetHeight:獲取對象相對於版面或由父坐標 offsetParent 屬性指定的父坐標的高度
offsetLeft:獲取對象相對於版面或由 offsetParent 屬性指定的父坐標的計算左側位置
offsetTop:獲取對象相對於版面或由 offsetTop 屬性指定的父坐標的計算頂端位置
event.clientX 相對文檔的水平座標
event.clientY 相對文檔的垂直座標
event.offsetX 相對容器的水平坐標
event.offsetY 相對容器的垂直坐標
document.documentElement.scrollTop 垂直方向滾動的值
event.clientX+document.documentElement.scrollTop 相對文檔的水平座標+垂直方向滾動的量
以上主要指IE之中,FireFox差異如下:
IE6.0、FF1.06+:
clientWidth = width + padding
clientHeight = height + padding
offsetWidth = width + padding + border
offsetHeight = height + padding + border
IE5.0/5.5:
clientWidth = width - border
clientHeight = height - border
offsetWidth = width
offsetHeight = height(需要提一下:CSS中的margin屬性,與clientWidth、offsetWidth、clientHeight、offsetHeight均無關)

  

上面的紅色部分以經講的很清楚  offsetwidth,現在里看看

在說說, scrollLeft :設置或獲取位於對象左邊界和窗口中目前可見內容的最左端之間的距離。

在說之前 首先來看一段文字:

scrollLeft:設置或獲取位於對象左邊界和窗口中目前可見內容的最左端之間的距離。

 

      1、innerHTML:inner(里面,元素),innerHTML是用來改變對象DH內部的HTML語句。而此效果中我們所用到的a.innerHTML=b.innerHTML就是b將自己的HTML元素賦予a,用在這里就如克隆一說。

       2、offsetWidth:是指對象包括邊框在內的寬度。與clientWidth不同,clientWidth指對象不包括邊框只包括內容的實際寬度。

       3、scrollLeft:我們知道scroll是滾動軸,那么scrollLeft就是指滾動軸自左向右滾出時距離左邊起點的距離。scroll有四個方向,大家依次類推。

       了解了這三項基本屬性,我們就有了初步實現滾動的思想。首先我們要知道一個塊就有這么寬,如果里面的內容也和外邊包裹它們的父標簽寬度一樣的話,那么滾動 條的寬度肯定也與內容一樣寬,根本就沒得滾。只有在里面內容大於父標簽內容並且對父標簽設置完固定寬進行超出部分隱藏。這樣即使在我們並沒有控制js時也 是可以實現手動拖拉滾動條的。了解這點后再說循環滾動,既然子標簽要超出父標簽才能實現滾動,那么循環滾動,循環展示一組圖片不就是需要兩組一模一樣的圖 片首尾相接,當第一塊的尾部滾過后第二塊的首部立馬相接,當然控制好精確到1px時,用戶是根本察覺不到是兩組圖片在做滾動,因為是相同的。說完原理,再 說實現辦法,我們已經知道了scrollLeft的意思,那么要讓圖片向左滾,無疑就是增加它的數值,在我們手動拖拉滾動條時也會觀察到向右拖拉時圖片是想做移動的,scrollLeft的距離在不斷增加。那么也就是說,要實現子標簽圖片的滾動,就要控制父標簽的scrollLeft。再加上計時器,讓父標簽的scrollLeft每過多久增加多少不久實現了自動的圖片滾動了嗎?下面請看代碼吧,在HTML的結構上也是需要做下詳解的。

 這是 一段網上找到,要清楚scrollleft 是父標簽的,scrollleft是個值,父標簽就是指的產生滾動條這個元素,,而滾動條也屬於,父標簽。

   下面來看一個簡單的例子:

HTML:

<div id="div1">

<div id="div2"><!-- 這里的div主要起控制不換行的作用,因為里面還要包裹兩個div -->

<div id="div3">

<a href="#"><img src="images/tu1.jpg" alt=""/></a>

<a href="#"><img src="images/tu2.jpg" alt=""/></a>

<a href="#"><img src="images/tu3.jpg" alt=""/></a>

<a href="#"><img src="images/tu4.jpg" alt=""/></a>

<a href="#"><img src="images/tu5.jpg" alt=""/></a>

</div>

<div id="div4">&nbsp;</div>

</div>

</div>

      使 用table制作還能減少css樣式的設置,省去很多浮動。但是table中的td元素之間的間距是需要解決的,如以上代碼中已經寫到在包裹圖片的 table標簽中加入cellspacing="0" cellpadding="0",當然也可以直接在css中這樣寫,table{border-collapse:collapse;},便可去除td之 間的間距,圖片折行引起的間距使用浮動解決,同時我們還要養成的習慣便是當子元素浮動后要對其父標簽設置overflow:hidden;否則其父標簽將 不再包裹子標簽,加border后便可看到。

     css:

body {margin:0;}

#div {border:5px #0ff solid;height:160px;width:800px;overflow:hidden;overflow-x:scroll;}

#div table td {overflow:hidden}

#div img {float:left;}

       js:

<script type="text/javascript">

vardiv=document.getElementById("div");//最外層div

var td1=document.getElementById("td1");//第一個td,里面包裹圖片

var td2=document.getElementById("td2");//沒有包裹內容(圖片)的td

td2.innerHTML=td1.innerHTML;//將第一個td中的內容賦予第二個td

function hs1(){

div.scrollLeft++;//外圍父標簽div的scrollLeft加加(上文有詳解)

}

var id=setInterval(hs1,10);//每過10毫秒加1,從而初步實現滾動

</script>

有了上述一個開端實現了圖片的初步滾動,我們能觀察到當滾動軸滾到右邊盡頭時就不再滾動了,我們又如何讓它從頭繼續滾動呢?請看下列代碼:(接上述代碼做延伸

<script type="text/javascript">

vardiv=document.getElementById("div");

vartd1=document.getElementById("td1");

vartd2=document.getElementById("td2");

td2.innerHTML=td1.innerHTML;

functionhs1(){

if(td1.offsetWidth<=div.scrollLeft){

//滾動軸停了,圖片必定也滾到盡頭了,這時就判斷第一個或第二個(二者同寬)

//的寬度(或加邊或不加邊)是不是已經大於或等於父標簽div的scrollLeft

div.scrollLeft=0;//如果上述條件成立,那么div的scrollLeft就從零開始

}else{

div.scrollLeft++;//不屬上述情況時就繼續++

}

}

var id=setInterval(hs1,10);

</script>

      運 行到這里就已經實現了無縫滾動,那么接下來要考慮的就是當用戶鼠標放上時停止滾動,離開時繼續滾動。思想也很容易理解,就是放上時清除計時器,離開時再加 上計時器。其實不用事件監聽的話要做到這一步只需兩句話,很容易。但是為了防止事件冒泡,我們還是需要使用時間監聽的方法解決。

      事件冒泡:css中,子標簽會繼承父標簽的樣式。js中,由於很多瀏覽器是沒有分層的,不能分層解析,子標簽就會繼承父標簽的動作造成事件冒泡。所以我們要盡量阻止冒泡。

      接上述代碼延伸:

<script type="text/javascript">

vardiv=document.getElementById("div");

vartd1=document.getElementById("td1");

vartd2=document.getElementById("td2");

td2.innerHTML=td1.innerHTML;

functionhs1(){

if(td1.offsetWidth<=div.scrollLeft){

div.scrollLeft=0;

}else{

div.scrollLeft++;

}

}

varid=setInterval(hs1,10);

functionhs2(){

addEventHandler(div,"mouseover",function(){clearInterval(id);});

//使用事件監聽的方法,如果此方法只被調用一次,就可以直接寫在這里的函數段里

addEventHandler(div,"mouseout",function(){id=setInterval(hs1,10);});

}

hs2();

function addEventHandler(target,type,func){

if (target.addEventListener){

target.addEventListener(type,func,false);

}else if (target.attachEvent){

target.attachEvent("on"+type,func);

}else{

target["on"+type]=func;

}

}//事件監聽(對於事件監聽的理解在《詳解tab切換四種方法》中有注解)

</script>

      一 步步實現了無縫循環滾動以及監聽用戶動作停止繼續后,就要繼續考慮另一種效果了,當圖片滾動到一定位置時會自動停止,停止多久后再繼續執行正常滾動,用戶 鼠標放上時也會停止,離開時繼續。這樣的效果我們都能聯想到的就是先命令div的scrollLeft進行到什么位置后清掉計時器,在使用 setTimeout的計時器控制其再隔多久繼續進行滾動。那么,我們如何才能獲取到每隔多長的距離才讓其停止呢,注意是“每”我原來試過用加法,顯然是 行不通的,一輪一輪的無限循環要加到什么時候。但是我們同學便想到了一個很巧妙的辦法,求余。求余的運算符號是%,求余也就是獲取倍數,就能實現每前進多 遠就清掉計時器的辦法。代碼解析請看下方代碼:

<script type="text/javascript">

vardiv=document.getElementById("div");

vartd1=document.getElementById("td1");

vartd2=document.getElementById("td2");

td2.innerHTML=td1.innerHTML;

varidd=null;//此處聲明計時器idd,否則在未讀取對象就有執行關於其的命令時報錯沒有對象。

function hs1(){

if (td1.offsetWidth<=div.scrollLeft){

div.scrollLeft=0;

}else{

div.scrollLeft++;

}

if (div.scrollLeft%160==0){

//這里便是求余的判斷,每當到div的scrollLeft能整除160這個數值的位置時,(數值我們可以自己設),

clearInterval(id);//就清掉計時器。

idd=setTimeout("id=setInterval(hs1,10)",1000);

//setTimeout的計時器,控制停止過一秒時繼續執行計時器id,也就是繼續滾動

}

}

var id=setInterval(hs1,10);

function hs2(){

addEventHandler(div,"mouseover",function(){if(idd){clearTimeout(idd);}clearInterval(id);});

//用戶鼠標放上時便又要多一句判斷,如果正在運行idd計時器時也將其清掉。

addEventHandler(div,"mouseout",function(){id=setInterval(hs1,10);});

}

hs2();

function addEventHandler(target,type,func){

if (target.addEventListener){

target.addEventListener(type,func,false);

}else if (target.attachEvent){

target.attachEvent("on"+type,func);

}else{

target["on"+type]=func;

}

}//事件監聽

</script>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM