如題 marquee在滾動時文字會有些微抖動
不知道該如何解決這問題 可能跟我內容會動態變動有關
html
<table>
<tr>
<td class=title>下一首:</td>
<td><marquee scrollamount=25><div id=req class=next></div></marquee></td>
</tr>
</table>
js
function next_call()
{
$.getJSON("data/complex.json",
function(b)
{
request_json=b.requestlist;
request_length=request_json.length;
currenttrack_json=b.currenttrack;
currenttrack_length=currenttrack_json.length;
currenttrack_html="";
request_html="";
for(q=0;q<1;q++)
{
var time_r=currenttrack_json[q].time_remaining_seconds;
var min=Math.floor(time_r/60);
if(min<10)
{
min="0"+min;
}
var sec=Math.floor(time_r%60);
if(sec<10)
{
sec="0"+sec;
}
request_html+='歌手:'+request_json[q].artist+"   ";
request_html+="歌名:"+request_json[q].title+"   ";
request_html+='專輯:'+request_json[q].album+"   ";
request_html+="時間:"+request_json[q].length+"   ";
currenttrack_html+="離下首播放還剩:"+min+"分"+sec+"秒";
}
request_html+="";
currenttrack_html+="";
$("#req").html(request_html+currenttrack_html);
}
)
}
先說原因
根據我的觀察,是 marquee 在處理長度時,根據的是一開始從左邊跑出來的長度
即使中途變更內文,他還是當作原先的長度處理。
因此,當中途改變時:
至於解決辦法, marquee 原本設計並沒有考慮到內文變更,所以最偷懶的方法是想辦法讓訊息的 width 一樣。
如果要做比較精細的控制,看是用 javascript 動畫,或是 svg+SMIL,或是CSS動畫。後兩者可能需要配合 javascript 來改變屬性。
另外,我個人是覺得不需要 0.5秒 送一次 ajax 啦。
用 timer 每秒更新一次就好,當時間變成 0 之後再送 ajax。
如果希望時間準確些,可以再配合每幾秒(例如15秒)校正一次就好。
用 CSS 動畫做的範例
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>marquee</title>
<style>
#myCssMarque{
width:300px;
position:relative;
border:1px solid;
overflow:hidden;
}
</style>
<script src="CssMarque.js" type="text/javascript"></script>
</head>
<body>
<div id="myCssMarque"></div>
<button id="testL">長</button>
<button id="testS">短</button>
<button id="testP">短(不重設動畫)</button>
<script type="text/javascript">
var t=new CssMarquee("myCssMarque",150);
t.setText("123");
document.getElementById("testL").addEventListener("click",function(){
t.setText("12345678901234567890");
});
document.getElementById("testS").addEventListener("click",function(){
t.setText("123");
});
document.getElementById("testP").addEventListener("click",function(){
t.setText("321",true);
});
</script>
</body>
</html>
CssMarquee.js
function CssMarquee(tagId,speed)
{
this.st=0; //0為沒在跑,1為正在跑
this.speed=speed; //速度,每秒幾像素
//容器相關資訊
this.tagId=tagId;
this.container=document.getElementById(tagId);
this.container.innerHTML="";
this.leftBorder=parseInt(getComputedStyle(this.container)["border-left-width"],10); //容器的 border
//建立 span (內部真正在跑的區域)
this.span=document.createElement("span");
this.container.appendChild(this.span);
this.span.textContent="marquee"; //這隨便給的初值
//建立 style (放置動畫 keyframe 參數)
this.myCss=document.createElement("style");
document.body.appendChild(this.myCss);
//設定動畫結束的 callback (用來重新下一輪動畫)
this.span.addEventListener('animationend',CssMarquee.prototype.onAniEnd.bind(this));
}
CssMarquee.prototype.setText=function(text,lenUnchange)
{
//當 lenUnchange 為 true 時,直接變更 textContent 即可
//例如變更倒數計時的時間,如果每次都重新設定動畫會卡卡的
//這時就可以用這功能(把第2個參數設為 true)
if(lenUnchange && this.st==1){
this.span.textContent=text;
return;
}
var rect0=this.span.getBoundingClientRect(); //span 原先的矩形
this.span.textContent=text;
this.span.setAttribute("style","\
position:relative;\
left:100%;\
"); //先清除動畫,以重新設定
var rect1=this.span.getBoundingClientRect(); //span 變更後的矩形
var rect2=this.container.getBoundingClientRect(); //容器的矩形
var total_t;
if(this.st==0){ //已經跑完了
total_t=(rect2.width+rect1.width)/this.speed;
this.myCss.innerHTML="\
@keyframes ani_"+this.tagId+"{\
0%{left:"+rect2.width+"px}\
100%{left:-"+rect1.width+"px}\
}\
";
} else { //正在跑
total_t=(rect0.left-rect2.left-this.leftBorder+rect1.width)/this.speed;
this.myCss.innerHTML="\
@keyframes ani_"+this.tagId+"{\
0%{left:"+(rect0.left-rect2.left-this.leftBorder)+"px}\
100%{left:-"+rect1.width+"px}\
}\
";
}
this.span.setAttribute("style","\
position:relative;\
left:100%;\
animation-name:ani_"+this.tagId+";\
animation-timing-function:linear;\
animation-duration:"+total_t+"s;\
");
this.st=1;
}
CssMarquee.prototype.onAniEnd=function()
{
this.st=0;
this.setText(this.span.textContent);
}
感覺好像文字還是有些微抖動 這應該是marquee本身的問題吧 不過還是感謝大大提供的方法 不過文字會跳到最右側之前的版本確實有 改天把ajax導入這個新版的marquee裡看看