讓你的特效更平順

前幾天在改hidden links時,因為物件的移動效果不太順暢,和網路上一些大大作的明顯差很多,就花了些時間看看到底問題出在哪, 才發現,我以前都是用function被呼叫的次數來決定移動的距離(其實也只是function跑一次移動多少而已),而其他人的code則是用時間來決定要移動到哪。

我以前的方法有兩個缺點,一就是移動可能很不順,二則是可能會因為重複的觸發起動條件而造成速度倍增,但是改用時間來作判斷的話就沒有這個問題。在javascript中要取得時間很簡單,應該是每個瀏覽器的方法都一樣(Safari、IE、Opera、Firefox這幾個我測試過都OK):

timestamp = new Date().getTime();

這樣就可以取得unix time stamp了(從1970年1月1日開始計算的時間戳記),只不過比較特別的是單位是1/1000秒,而要使用這個時間戳記,你還需要另外一個時間戳記記錄你的特效開始的時間。有了這兩個時間戳記後,要讓效果能跑,還需要幾個東西,一是物件的起迄點,二是特效要花多久時間(週期),三是移動的方式(ex: 要減速效果。也可以說是位置的時間函數)。

以上幾樣東西都設定好了之後,我們就可以寫主要的script了,假設我的時間戳記變數名稱是ts、開始的時間戳記是st、物件要從sp處移動到ep處、移動要花一秒鐘,用等速度移動,那我可以寫成下面這樣:

ts = new Date().getTime();
p = (ts - ss) / 1000;
p = (p>1)1:p;
target.style.top = sp + (ep - sp) * p + "px";
if (p == 1)
{
	clearInterval(Interval);
}

第一行在取得現在的時間,第二行則是算現在是進行到整個動作的那個部分(幾個週期),第三行則是避免移動過頭,第四行才是指定新的位置給物件,接下來的if回圈則是動作結束的處理,大概的流程就是這樣,我把我的hidden links的這部份的code貼在下面,可以看的更完整:

function hlGo (type)
{
	if (!ts && !(type ^ hlFlag))
	{
		(type)?(tS.display = "block",delEvent(tA, "mouseover", hlMouseIn)):delEvent(body, "mousemove", hlMouseMove);
		ss = ts = new Date().getTime();
		this.Interval = setInterval("hlMove("+type+");", 20);
	}
}

function hlMove (type)
{
	ts = new Date().getTime();
	p = (ts-ss)/period;
	p = (p>1)?1:p;
	p = (type)?p:1-p;
	tS.top = iP+Math.sin(p*Math.PI/2)*tH+"px";
	if (isO) tS.opacity = p*0.96;
	if (!(p - type))
	{
		if (type && autofocus) tList.firstChild.firstChild.focus();
		ts = 0;
		clearInterval(this.Interval);
		(type)?addEvent(body, "mousemove", hlMouseMove):(tS.display = "none",addEvent(tA, "mouseover", hlMouseIn));
	}
}

要觸發事件只要呼叫hlGo這個function就好了,有多的判斷都是針對hidden links的需要放上的,除了hlGo裡面會先判斷ts受否不存在才繼續,這是為了避免重複觸發動作,當然事件結束就要把ts給清除掉(設為0)。