canvas動畫之三 -- 黑客帝國文字掉落效果
今天要實現的效果是黑客帝國裡面的文字掉落效果,先來看一下圖
點選這裡,檢視demo
其實效果也是比較好實現的,只要計算出每個文字該出現的地方,然後繪製文字就可以了。
下面就來說具體的實現方法吧。
首先,新建頁面寫上canvas標籤,在js中獲取到並設定高寬:
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
//設定canvas大小,全屏顯示
setSize();
//設定大小的函式
function setSize(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
</script>
canvas標籤設定完了之後,然後再來設定一個數組,也就是從螢幕上掉落出來哪些文字,當然這裡設定什麼都可以,我設定的是0~9、a~z,為了簡單我就是使用了split方法將字串轉換為陣列:
var txt = "0123456789abcdefghijklmnopqrstuvwxyz" ;
var arr = txt.split("");
接下來就該設定一下字型的大小和螢幕總共能容納多少列了,這裡我把字型大小設定為16px,為了方便計算這裡先設定為16,然後用瀏覽器的寬度除以字型大小,就能計算出來螢幕可以容納多少列文字,還需要設定一個數組,來儲存每一列中的文字該在哪裡繪製,當然每列第一個字都是從螢幕最上面開始,需要初始化一下:
//字型大小
var font_size = 16;
//多少列,整數
var column = Math.floor(canvas.width / font_size) ;
//每列文字繪製點
var drop = [];
//初始化陣列
for(let i = 0 ;i<column ; i++){
drop[i] = 1;
}
剛剛忘了一點,沒有設定onresize
,這裡設定一下,當然這個在什麼時候設定都是可以的,在window上新增onresize
事件,瀏覽器視窗改變時重新計算canvas
的大小:
window.onresize = function(){
setSize();
}
function setSize(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
現在準備工作都完成了,接下來就開始繪製文字效果吧,前面已經定義了陣列,現在需要從陣列中隨機取得一個數字,通過Math.random()產生隨機數獲取,輸出文字時使用fillText()可以在指定位置輸出文字,當每一列中繪製的文字超過瀏覽器的高度時,則從0開始重新繪製,當然如果所有的列都是在佔滿瀏覽器高度再重新繪製時這樣的效果並不好看,所以我們需要一個隨機數,當隨機數大於0.9的時候就重新繪製,繪製完每一列文字的時候,需要儲存一下下一次該列文字該在什麼地方出現:
//逐行輸出文字
for (var i = 0; i < drops.length; i++) {
//隨機取要輸出的文字
var text = txts[Math.floor(Math.random() * txts.length)];
//輸出文字,注意座標的計算
ctx.fillText(text, i * font_size, drops[i] * font_size);
//如果繪滿一屏或隨機數大於0.95(此數可自行調整,效果會不同)
if (drops[i] * font_size > c.height || Math.random() > 0.95){
drops[i] = 0;
}
//用於Y軸座標增加
drops[i]++;
}
在上面這個迴圈之前為了讓效果更好看,我們需要讓背景透明度逐漸變化,並且還需要設定好字型,所以整個draw()函式如下:
//輸出文字
function draw() {
//讓背景逐漸由透明到不透明
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
ctx.fillRect(0, 0, c.width, c.height);
ctx.fillStyle = "#0F0"; //文字顏色
ctx.font = font_size + "px arial";
//逐行輸出文字
for (var i = 0; i < drops.length; i++) {
//隨機取要輸出的文字
var text = txts[Math.floor(Math.random() * txts.length)];
//輸出文字,注意座標的計算
ctx.fillText(text, i * font_size, drops[i] * font_size);
//如果繪滿一屏或隨機數大於0.95(此數可自行調整,效果會不同)
if (drops[i] * font_size > c.height || Math.random() > 0.95){
drops[i] = 0;
}
//用於Y軸座標增加
drops[i]++;
}
}
接下來只要讓它不斷的迴圈繪製就可以了:
init();
//初始化
function init(){
setSize();
setInterval(draw,50);
}
然後整個絢麗的效果就完成了,是不是很簡單呢。
下面是整個程式碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>黑客帝國</title>
<style>
*{
padding: 0;
margin:0;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
setSize();
var arr = "0123456789abcdefghijklmnopqrstuvwxyz".split("");
var font_size = 16;
var column = Math.floor(canvas.width / font_size) ;
var drop = [];
for(let i = 0;i<column ; i++){
drop[i] = 1;
}
init();
//初始化
function init(){
setSize();
setInterval(draw,50);
}
//輸出文字
function draw(){
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "#0F0"; //文字顏色
ctx.font = font_size + "px arial";
//逐行輸出文字
for(var i = 0;i<drop.length ; i++){
//隨機輸出文字
var text = arr[Math.floor(Math.random()*arr.length)];
//輸出文字,座標重新計算
ctx.fillText(text,i*font_size, drop[i]*font_size);
//如果繪滿一頁或者隨機數超過0.9則重新繪製
if(drop[i] * font_size >canvas.height || Math.random() > 0.9){
drop[i] = 0;
}
drop[i] ++ ;
}
}
window.onresize = function(){
setSize();
}
function setSize(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
</script>
</body>
</html>