滾動字幕的實現

2021-09-19 20:07:24 字數 3509 閱讀 3002

滾動字幕,簡單來說,就是從下往上,把一些內容順序組織之後,同步移動。

這個看似很簡單的效果,在配合實際場景的「內容產生不確定性」這個特點之後,就會有一點點挑戰了。至少,比可以亂飛,可重疊的 b 站式彈幕要麻煩得多。

從上面看,也許初步的思路,是建立很多 div 之後,不斷計算它們的位置,就實現了同步滾動。這樣處理不是不行,只是計算每個 div 位置,會有一些效能浪費,同時,因為每個 div 的高度是可能不同的,在判斷「進入」及「完成」時,總是需要先取得正確的物件,並獲取其高度之後,才能計算。這也就是說,你必須得保持每乙個 div 的引用。這可不是明智的辦法。

更容易的處理方式,是把這些 div 打包處理:

在單個包內部,通過 css 調整好間距之後,滾動的效果只是單個塊滾動的結果。判斷「進入」用「完成」需要保持每個塊的引用,這在大部分時候,要比單個 div 少乙個數量級。當然,極端情況,每個塊中只有乙個 div ,也就退化到前面一樣的場景了。

為了達到滾動不間斷的效果(單個塊的高度,有可能比可視區高度大,也可能小),我們需要在適當的時候,在底部加入新的塊。同時,為了穩定頁面資源的消耗,也需要把完成顯示的塊給刪除掉。

我個人在想像這個過程的時候,很自然會聯想到機槍的裝彈夾及換彈夾的過程。顯示的過程,就是在輸送彈夾的過程。內容移出顯示區,就是打出了一顆子彈。乙個彈夾的所有子彈都打完的時候,這個彈夾就需要被卸掉。同時,彈夾的輸送需要是不間斷的,乙個彈夾接著乙個彈夾(但是它們不能有重疊)。

基於這個比喻,整個過程大概變成了:

再看準備過程。

上面的第一步,當我們獲取到乙個彈夾的時候,把它置於初始位,然後控制它開始往上滾動。當滾動到第二步的位置時,我們需要再得到乙個新的彈夾,把它置於第一步位置,如此反覆。

在這一步,需要的抽象,是「獲取彈夾」這個行為。

我們可以定義乙個「彈夾工廠」,當需要彈夾的時候,總是去找它使就可以了。它一定會返回乙個彈夾,哪怕是空彈夾。至於,這個「彈夾工廠」自己是如何獲取子彈,如何生產彈夾,可以完全內化。

額外的這個**過程,是為了處理一種「意外場景」。即在內容滾動完,又沒有新的內容產生的時候,可以用舊的內容來代替。

但注意一點,在舊的內容滾動過程中,新的內容可能隨時產生,所以,為了能盡快把新內容顯示出來,我們可以把舊內容彈夾,永遠只放一顆子彈,這樣,這個彈夾就很「小」。一旦它達到第二步位置,我們就有機會去判斷是否有新內容需要馬上被放進來。

**過程本身,也就是當彈夾被顯示完之後,這個彈夾中的子彈,再次被送到彈夾工廠。當然,這個工廠彈夾生產策略,可能和新內容的那個工廠不同。除了前面說過了,乙個彈夾只放一顆子彈之外,還有,比如,舊內容,一般我們只需要保留最新 n 條。

至此,整個問題就差不多是這樣了。

滾動的實現,肯定是只能放在頁面,通過控制 dom 的屬性來實現了。這種跟頁面相關的,一般我們放在後面再去處理。因為與頁面相關的**,我們需要在瀏覽器中除錯。而與介面無關的部分,就容易得多了,只需要開啟編輯器,寫完,執行就好了。

非介面的邏輯,很清楚地,就是上面的右側,「彈夾工廠」,「彈夾」,「子彈」這套東西。

class bullet 

}class clip

fill(bullet)

isempty()

getbulletamount()

getbulletlist()

}class clipfactory

receive(bullet)}}

}pop()

return clip;

}}class standbyclipfactory extends clipfactory

}

上面**中,最後多了乙個standbyclipfactory,是備用彈夾工廠。因為需要處理它的邏輯,所以彈夾工廠多出來了兩個引數,bulletmaxamountperclipmaxclipamount,用於定義,單個彈夾的子彈數,及,工廠可儲存的最大彈夾數。

所以定義寫好之後,可以加上隨機邏輯讓它們跑起來看看:

function main() , math.random() * 1000)

}const fill = () => , math.random() * 100)

}const check = () => else

settimeout(() => , math.random() * 500)

}fillstandby();

fill();

check();

}if (require.main === module)

滾動的 dom 結構是很簡單的:

哈哈哈

哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈

再看執行流程,無非是:

其實談到了「獲取策略」,和「**策略」,很自然會想到「優先彈夾工廠」的邏輯,即,實現,某些內容一旦產生,是直接優先「插隊」顯示的。這步就不延展了。

流程列清楚了,**不難:

class engine 

createclipelement(clip));

return dom;

}move(clip, nextcallback, endcallback)px, 0)`;

ele.style.opacity = 1;

const animation = () => px, 0)`;

if( (y <= nexty) && (status == 'before'))

if( (y <= endy) && (status === 'in') )

if(status === 'end')

requestanimationframe(animation);

};animation();

}// 獲取策略

getnewclip(callback), 500);

return;}}

callback(clip);

}// **策略

onclipend(clip));

}run());

});}

}

Winform實現滾動字幕

寫了個winform滾動字幕的 可以由下往上滾,由左往右滾,由右往左滾 其中可以慢慢的滾,類似led滾動螢幕 寫了乙個類以便呼叫 graphics ghf null public lablemgr label lb,string rolltext,graphics gh,string rolltyp...

c 滾動字幕的實現

在c 中其實滾動螢幕的實現很簡單,只需要用到graphics.drawstring方法.graphics.drawstring string s,font font,brush brush,pointf point 在指定位置並且用指定的 brush 和 font 物件繪製指定的文字字串。其中,我們...

C 滾動字幕的實現

效果圖 就是這一行字橫著移動沒有背景,透明的。需要timer控制項1個 form的 using system using system.collections.generic using system.componentmodel using system.data using system.dra...