[Javascript]橫向跑馬燈滑鼠移開回到一開始

  • 1787
  • 0
  • 2015-06-16

摘要:[Javascript]橫向跑馬燈滑鼠移開回到一開始

首先提醒,

程式沒有做優化,但其實很多是可以合併處理的。

先看效果網頁(請移動滑鼠到四個不同的跑馬燈上):

https://googledrive.com/host/0B7hg_8WvMyfJRHZVemV2MjdpbTg/

由於是純Javascript寫的,想自己研究可以直接下載網頁或檢視原始碼。

因為網上看到的滑鼠控制多半是移開就停止Timer,文字就卡在中間,

但我要的結果是滑鼠移開,文字就回到一開始的位置才能重新跑。

至於展示的四種情況,

其實是區分文字長或短(有沒有超過表格寬度)以及是否循環跑。

我知道很多人喜歡在跑馬燈加圖片,這樣的作法也是可以辦得到的。

 

第一步都是先計算文字總長度,

如果直接計算表格裡的文字,多半會受限於表格的寬度,

因此要另外用div包住文字來計算。

這段div是這樣的:

<div id="Test" class="txtWidth">testtesttest</div>

id是用來取得文字寬度,testtesttest就是你的文字內容,

這部分的css則是:

.txtWidth
{
    position: absolute;
    visibility: hidden;
    height: auto;
    width: auto;
    white-space: nowrap;
}

因此文字長度用js來算就是:

var widtmp = getById("Test").clientWidth;

再來,就是要有感應區域,感應區域就是指滑鼠移入移出的介面設計。

以我的範例來說,就是一個table的最上面那一格顯示此table的標題,

table第二層會有左右兩個區塊(以顏色區隔)。

因此感應區域就是上面的標題(id='titleSD')。

撇除table的部分,感應區也是一個DIV

<div id="titleSD" style="cursor:default;"></div>

cursor部分只是為了讓滑鼠游標保持箭頭符號。

接著是跑馬燈主要的部份,這部分其實是可以統一的,

結構就是一個專門移動的div,裡面包含一定要display:inline-block(保持在同一行)的內容。

循環模式來說,其內容就是內容1+中間間隔+內容2,而內容1=內容2

若是不用循環的話,直接在div:snname加入文字內容(或圖片、超連結)就可以了,

middle的處理則是依照字串長度來衡量,

我的作法是超過表格寬度指定middle,若無超過就用表格寬度減掉內容寬度來算。

因此判斷是否超過表格寬度的部分則是:

        var middle=0; 
        var widtmp = getById("Test").clientWidth;
	var widdiv = getById("snname").clientWidth;
        // 若文字寬度小於表格寬度
	if(widtmp<widdiv){
		middle=(widdiv-widtmp);
		getById("middle").style.width = middle + "px";
	}
        function getById(id){
		return document.getElementById(id);
	}

widtmp是內容寬度(在這裡是文字寬度),

widdiv是表格寬度(即上方深綠色區域寬度)。

為了使用方便,我自己是另外建一個function叫getById取代原本的document.getElementById的部分。

這邊是假如內容寬度小於表格寬度,若是大於表格寬度則是:

        var middle2=100; //假設文字中間間隔100px
        //文字長時,給循環字串之間的間隔
	getById("middle2").style.width = middle2 + "px";

然後就可以進到感應區的mouseover與mouseout部份了:

        var t;        // timer控制
        var num=0;    //已經移動的距離
        var steps=3;  //每次移動距離,數字越大跑越快,因此建議不要超過5
        //文字短,文字從右往左跑並循環
	if(isNull("titleSD")){
		getById("titleSD").onmouseover=function(){
			t=setTimeout(moveDiv, 100);    //以0.1秒控制timer
		}
		getById("titleSD").onmouseout=function(){
			num=0;                         //若滑鼠移開則回到初始狀態
			getById("snname").style.left=num+"px";
			clearTimeout(t);
		}
	}
	function moveDiv(){
                if(widtmp<=widdiv){
		        if(num-steps<=0-(widdiv)) num=0;       //此為內容寬度小於表格寬度的做法
                        else num-=steps;
                }else{
                        if(num-steps<=0-(widtmp+middle)) num=0; //此為內容寬度大於表格寬度的作法
		        else num-=steps;
                }
		getById("snname").style.left=num+"px";
		t=setTimeout(moveDiv, 100);
	}

        function isNull(id){
		if(document.getElementById(id)!=null) return true; return false;
	}

為了方便我創了isNull方法判斷是否找到控制項,

說穿了,跑馬燈最陽春的做法就是透過timer讓內容改變x座標,至於內容怎麼顯示再用目前位置或移動的距離作修改。

 

所以文字短,跑馬燈循環的程式碼就是:

        var t;  var num=0;
        var middle=0;
        var steps=3;
	var widtmp = getById("Test").clientWidth;
	var widdiv = getById("snname").clientWidth;
       // 若文字寬度小於表格寬度
	if(widtmp<widdiv){
		middle=(widdiv-widtmp);
		getById("middle").style.width = middle + "px";
	}
       //文字短,文字從右往左跑並循環
	if(isNull("titleSD")){
		getById("titleSD").onmouseover=function(){
			t=setTimeout(moveDiv, 100);
		}
		getById("titleSD").onmouseout=function(){
			num=0;
			getById("snname").style.left=num+"px";
			clearTimeout(t);
		}
	}
	function moveDiv(){
		if(num-steps<=0-(widdiv)) num=0;
		else num-=steps;
		getById("snname").style.left=num+"px";
		t=setTimeout(moveDiv, 100);
	}

	function isNull(id){
		if(document.getElementById(id)!=null) return true; return false;
	}
	function getById(id){
		return document.getElementById(id);
	}

使用者介面的部分則是:

<table bgcolor="#006600" cellpadding='0' cellspacing='0' style='border:0;width:160px;height:120px;display:inline-table;margin: 0px 0px 20px 20px;table-layout:fixed;white-space: nowrap;'>
<tr><td height='30' colspan='2' style='overflow:hidden;padding-left:5px;'><div id="titleSD" style="cursor:default;"><div id="snname" class="marquee"><div class="marquee inline">testtesttest</div><div id="middle" class="marquee inline"></div><div class="marquee inline">testtesttest</div></div></div></td></tr>
<tr><td bgcolor="#CC0000"></td><td bgcolor="#00FFCC"></td></tr>
</table>

而所有的CSS設計則是:

<style type="text/css">
.txtWidth
{
    position: absolute;
    visibility: hidden;
    height: auto;
    width: auto;
    white-space: nowrap;
}
.marquee{
	color:#FFFFFF;
	position:relative;
	width:auto;
	white-space:nowrap;
}
.inline{
	display:inline-block;
}
</style>

所有程式碼請直接下載網頁或滑鼠右鍵→檢視原始碼查看即可。

 

這樣做的缺點就是要自己算何時接續下一個循環的字,

當內容2的LEFT跑到相對位置0的時候,將內容1的LEFT巧妙的設成0,

如此一來內容2和內容1好像重疊在一起(畢竟內容2只是內容1的複製),造成循環的錯覺。

 

再次提醒:

循環跑馬燈要算好接續的部分,若原本的內容1有設padding或margin就要把padding或margin那些也算進去喔!

 

原始檔下載:

testMarquee.zip