摘要:[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那些也算進去喔!
原始檔下載: