楊慶虎
(貴州城市職業學院,貴州 貴陽 550025)
Web 程序設計、移動應用開發,都需要良好的UI界面和有趣的交互。運動不僅能有效地突出重點、吸引客戶的眼球,還能增加系統的趣味性,實現靜止對象無法實現的功能。如何讓圖片、對話框、導航條、留言面板等網頁元素根據需要實現特定的運動特效成為系統UI設計師關注和研究的重點。解決JavaScript對象運動問題最簡單和有效的方法就是采用運動框架。框架的概念最早起源于Smalltalk 環境,其中最著名的框架是Smalltalk-80 的用戶界面框架MVC(Model-View-Controller),即將對象、屬性、目標等參數封裝到一個函數中,使用時調用函數即可,被封裝好的函數即稱為框架。
基礎運動是高級運動研究的基礎,所有JavaScript運動都包括運動驅動事件、運動方式、運動速度等。運動驅動事件是驅使運動的觸發事件,如頁面裝載、鼠標移入移出、鼠標點擊等。運動方式主要是對象運動前后屬性的變化,如實現位置改變的左右移動、上下移動,實現特定屬性如透明度變化等。運動速度主要由定時器和預設速度決定。
構建運動框架要注意兩點:首先,在開啟運動前要關閉已有定時器;其次,在運動框架中要將運動和停止使用if…else…語句隔離開,不能攪和在一起,否則會出現預想不到的Bug。下面以常見的側邊欄分享為例進行說明。側邊欄由div1 和span 標簽組成,側邊欄分享JS代碼如下:

上述代碼定時器關閉條件為Math.abc(oDiv.offsetLeft-iTarget) 在實際項目開發中,勻速運動的情況比較少見,更多的是緩沖運動,如JavaScript 中的手風琴效果等。緩沖運動實現的原理是運動對象離目標值越大運動速度越快,反之則越慢,速度的快慢由距離的遠近決定,用iSpeed 表示對象速度,iTarget 表示目標值,offsetValue表示當前值,m表示速度系數,則緩沖運動的速度公式可表示為:iSpeed=(iTarget-offsetValue)/m。 例如需要移動的對象為div1,設計div1 的初始水平位置為0,通過分析知,div1 緩沖運動的速度在不斷減小,當值減小至計算機內存無法精確表示時,此時一直以這個速度循環運行,但對象無法移動,且對象位置停留在較近的某一點但沒有到達目標點。經分析知引發此問題的原因是“ iSpeed=(iTarget-oDiv.offsetLeft)/m;”。因此,需要對程序進行改進,為了保證對象向左移動或向右移動均有效,引入JavaScript中的取整函數,當速度大于零向左移動時向上取整,即使用cell函數,當速度小于零向右移動時向下取整,即使用floor 函數,因此在速度語句下面增加速度取整語句:iSpeed=iSpeed>0?Math.ceil(iSpeed):Math.floor(iSpeed);同時,由于取整的實現,對象運動速度最后必為1,隨著時間的推移,運動物體必將到達目標點,因此可將oDiv.offsetLeft>=iTarget 中的判定條件修改為“==”即可。經實驗運動對象能實現緩沖效果并到達目標點。 如圖1 所示,設可視窗口頂部隱藏區域的高度為scrollTop,窗口可視區域高度為clientHight,側邊欄高度為offsetHeight,當div 對象垂直居中時不難算出側邊欄的頂部距離Top,其計算公式為,Top=scroppTop+(clientHeight-offsetHeight)/2。采用水平緩沖運動原理,可以實現對象div的垂直居中效果。 圖1 側邊樣垂直居中示意圖 瀏覽器兼容問題一直是JavaScript設計的難題,窗口隱藏區域高度取值(scrollTop),就存在瀏覽器兼容Bug,此處通過或運算給予解決,解決的代碼為“scrollTop=document.documentElement.scrollTop||document.body.scrollTop;”。另外,通過測試,發現div1 對象到達目標后有輕微的抖動,經檢查發現t 值為小數造成,因此,對目標值t采用parseInt(t)取整即可解決Bug。 多物體運動要解決搶占定時器問題,必須為每個運動對象定義獨立定時器,同時,不僅要弄清楚運動目標點是哪里,還要弄清楚運動的對象是什么。例如,下列代碼實現了一組div 寬度隨著鼠標移入變寬,移出變窄的運動效果。 在多物體運動中,運動對象是多個,因此不能再使用document.getElementById()方法來獲取對象,而是要通過諸如getElementsByTagName()、document.getElementsByClassName()等方式獲取。上述代碼中“oDiv[i].timer=null;”為每個div 設置獨立的定時器,避免了搶占定時器問題,在對象傳參過程中不僅傳遞了目標值iTarget,而且還明確了運動對象obj。 在多物體運動中所有的屬性和變量必須獨占,不能共用。例如,對多個div 進行透明度的運動,此時,必須為每個對象單獨定義透明度存儲對象,如果共享則可能會出現對象A 要讓透明度增大,對象B 卻要讓透明度減小的矛盾。 在任意值運動框架中首先要解決offset(offsetWidth、offsetHeight)Bug 問題,offset 值不僅包括樣式中對象的長(Width)、寬(Height)值,還包括了邊框等值。 如上述代碼隨著時間的推移div 對象的寬度不斷變窄,但如果給div 中的樣式加上邊框后,實際的運行效果則會隨著時間的推移不斷變寬,這與程序的初衷相悖。為什么會出現這種相悖現象?設對象的初始寬度(style.width)為100,加了1 像素的邊框后,由于offset 值包括邊框的寬度,因此offsetWidth 值為102,減去1 后對象寬度變為101,如此循環,不難看出對象的寬度會逐漸增大。 解決上述問題最有效的方式即獲取對象的實際寬、高(width、Height)值,可封裝一個函數,代碼如下: 然后將對象寬度修改語句“oDiv.style.width=oDiv.offsetWidth-1+'px';”變更為oDiv.style.width=parseInt(getStyle(oDiv,'width'))-1+'px';即可。 任意對象任意值的運動框架代碼如下: 可將上述代碼封裝到js文件中(如MoveFrame.js)供其他運動場景使用。 使用封裝好的startMove(obj,attr,iTarget)運動框架解決系統開發中的flash運動效果如圖2所示。 圖2 運動框架效果圖 ⑴鼠標移入瀏覽窗口左或右邊,以淡入淡出顯示左或右導航箭頭,并且可以點擊箭頭實現圖片換頁。 ⑵大圖換頁方式為從上向下拉,對應縮略圖透明度增加至100%,且位于縮略圖中間。 ⑶點擊縮略圖,縮略圖透明度增加至100%,且游覽窗口顯示對應大圖。 ⑴采用CSS樣式為頁面布局,布局效果如圖1。 ⑵引入封裝好的運動框架js文件。 ⑶代碼實現。 在代碼實現中可以通過語句“aEle=document.getElementsByTagName('*');”選出樣式中的所有元素。語句“if(this.index==iNow)return;”避免重復點擊激發運動效果。由于主窗口圖層堆疊在一起,前面的圖層擋住了后面的圖層,因此,必須借助語句“aBigLi[iNow].style.zIndex=iMinZindex++;”將當前圖層移至頂層,這樣才能使用戶看到圖片向下拉伸的運動效果。設有m 張縮略圖,點擊首張和最后一張縮略圖時,其位置不變,即為0 和-(m-2)*li.width,點擊其余圖片時移動至中間,因此,其位置變化為-(m-1)*li.width,即使用if(iNow==0){…}else if(iNow==aSmallLi.length-1){…}else{…}語句控制。tab()函數實現了縮略圖與大圖運動的關聯,后續程序中多次用到,因此進行了封裝。 上述程序應用運動框架封裝實現了瀏覽窗口導航箭頭換頁,大圖、小圖運動效果等,程序簡潔,易讀性好,代碼利用率高。運動框架功能強大,不僅可以較好的完成上述運動效果,還可以用該框架完成諸如自動播放、增加圖片說明等運動事件處理。 運動框架是構建系統運動的主要方式之一,應用好運動框架不僅能高效地實現運動效果,使程序簡潔、易讀、提高代碼復用率,而且還能減少程序維護工作量,提高系統維護效率。本文從前端運動設計驅動事件、運動方式、運動速度等基礎進行分析,對單物體勻速運動、水平緩沖運動、側邊欄緩沖居中的特點進行研究,并基于單物體運動的基礎構建了多物體任意值運動框架,解決了系統中任意對象、任意屬性、任意值的運動設計。設計的案例可以應用于系統開發中,也可以做為教學實踐案例。在系統的實際應用中可以基于JSON數據對框架改進和應用,實現完美運動框架。2.2 水平緩沖運動
2.3 側邊欄緩沖居中

3 多物體運動框架
3.1 多物體單屬性運動框架

3.2 多物體任意值運動框架




4 運動框架使用案例
4.1 使用案例場景說明

4.2 實現說明
5 總結