LED跑馬燈之二,led跑馬燈
這是上一篇文章的地址:http://blog.csdn.net/pandeng4639088/article/details/46550257
上一篇對跑馬燈的原理及規律進行了一次分析,雖然本來故事會在那裡結束的,但結果我在中午去吃飯途中,又想了想,既然都給A對象加了一個假想長度,那為什麼不將這個假想長度映射回A本身呢?而且現實生活中也有這樣的效果,就是當B超出A長度時,超出的部份,直接在A開始的位置出現,類似效果如下:
好,這種效果又如何?呢?同樣,我們也是通過事實的表面來分析得出事物的規律,利用規律來解決問題。
(1)如所示,當B對象剛超出A時的情景,我們把剛超出的部份B0映射到A0上去,那如何知道計算這個下標映射關係?,假設映射的起始下標位置為S1,那麼就有S1 = S%A.len,A.len表示A數組的長度,所進行的操作是A[i].style.backgroundColor = B[j]。
但這個仍然得不到合理的頭緒,因為接下來的迴圈沒法做了,因為問題在於I這個下標身上,I的值為0的話,那相當於這個迴圈結束了!但我們又想到,I=S1=S%A.len,那,為什麼不用S來表示I?,讓I=S,執行操作為A[i%A.len].style.backgroundColor = B[j]。
所示得到一個過程如下:
for( var i= S, j=0; i>=0; i--, j++ ){
if( j < B.len ){
A[ i%A.len ].style.backgroundColor = B[j];
}else{
A[ i%A.len ].style.backgroundCOlor = '#ccc'; //預設顏色
}
(2)那如果B數組遍曆完後如所示:
經過分析得出,當S > ( A.len + B.len - 1 ) ,即S增長到A和B兩者的長度之和時,映射剛好把B全部映射完畢,說明這一輪就結束了。
於是得出:
if( S > ( A.len + B.len - 1 ){
//結束,重新開始新的一輪
S = S%A.len;
}
似乎,分析就到此結束了,但運行後我發現,走完一輪後,發現並沒有得到正確的運行結果,為什嗎?因為i的值是一直遞減的,一直減到為0為止,所以我們映射過去的顏色又被預設色覆蓋了。那我們怎麼知道在哪裡停下?即我們怎麼知道哪一部份被映射了?上面兩張圖中都有一個E的標記,這個E就是表示I結束的位置。而E的計算公式如下:
當在(1)圖狀態時,E = S%A.len + 1 = 5%5+1 = 1
當在(2)時,E=0,為什麼是=0,而不是同(1)一樣?答案是已經到了結尾而重新開始的地方,那E當然是歸0啦!
但是你們也許還有疑惑,那正常情況下的呢?公式是不是仍然正確?正常情況下,E的值仍然是0,因為S並未超出A數組的長度,當只有S超出A的長度時,即進行映射的時候,這個時候,E才會進行移動,當映射結束的時,即最終狀態,E也需要迴歸到正常狀態下,即0。
所以,代碼如下,這裡我還添加了一個控制按鈕,方便進行查看各個過程:
<pre name="code" class="html"><!DOCTYPE html><html><head><title>Test4</title><meta http-equiv="Content-type" content="text/html;charset=utf-8" /><style type='text/css'>.box{ width:500px; margin:20px auto; }.box ul{list-style: none;}.box ul li { width:20px; height: 20px; background-color: #ccc; float:left; text-align:center;}</style></head><body><input type="button" value='Start/Stop' onclick="switchLED()" /><div id='box' class='box'><ul><li></li><li></li><li></li><li></li><li></li><li></li><li></li> <li></li><li></li><li></li><li></li><li></li></ul></div></body><script type="text/javascript">//顏色數組(簡稱B)var objB = [ '#FF0000', '#FF3300', '#FF6600', '#FF9900', '#FFCC00' ];var startPos = 0; //這裡是一個數組遊標,標記當前從哪個位置開始變化設定顏色var objA = undefined; //進行變化的對象var timer = undefined;init();//初始化function init(){//我這裡用的是li標籤,如果你的是div,則將所有需要變化的div存在在一個變數中,我這裡放的是objA這個變數.objA = document.getElementById('box').children[0].children; //簡稱A對象//調用跑馬燈函數fLEDScrollerB();}function fLEDScrollerB(){var endPos = 0;//當開始進行映射if( startPos >= objA.length ){endPos = startPos%objA.length+1;}//映射結束狀態,歸0操作if( startPos > ( objA.length + objB.length - 1 ) ){startPos = startPos%objA.length;endPos = 0;}//i下標的值不能超過endPosfor( var i= startPos, j=0; i>=endPos; i--, j++ ){if( j<objB.length ){objA[i%objA.length].style.backgroundColor = objB[j];}else{objA[i%objA.length].style.backgroundColor = '#ccc';}}startPos++;//間隔100毫秒進行一次變化timer = setTimeout( 'fLEDScrollerB()', 100 );}//開關函數function switchLED(){if( null == timer ){fLEDScrollerB();}else{clearTimeout( timer );timer = null;}}</script></html>
效果如下:
注意,這種映射方式有其限制,就是A數組的長度不能小於B數組的長度,不然,映射的長度都不夠,會造成重複覆蓋的後果!