背景:
一日在網上閒逛的之時,忽然看到一個利用JQ插件實現canvas實現的電影黑客帝國的小Demo。以爲創意不錯,就下載下來研究一下。html
$(document).ready(function() { var s = window.screen; var width = q.width = s.width; var height = q.height; var yPositions = Array(300).join(0).split(''); var ctx = q.getContext('2d'); var draw = function() { ctx.fillStyle = 'rgba(0,0,0,.05)'; ctx.fillRect(0, 0, width, height); ctx.fillStyle = 'red'; ctx.font = '10pt Georgia'; yPositions.map(function(y, index) { text = String.fromCharCode(1e2 + Math.random() * 33); x = (index * 10) + 10; q.getContext('2d').fillText(text, x, y); if(y > Math.random() * 1e4) { yPositions[index] = 0; } else { yPositions[index] = y + 10; } }); }; RunMatrix(); function RunMatrix() { Game_Interval = setInterval(draw, 1000); } });
全程100行不到的代碼,主體的核心就是定時器調用canvas進行繪畫處理。要是讓我這種段子手來寫,估計我把敲爛鍵盤都想不出這樣營造效果。藝術細胞真的很重要咕~~(╯﹏╰)
jquery
老王:「等等大棒!不是說js+canvas實現黑客帝國矩形雨,但是你這個附上的代碼分明是jQ+canvas.」git
老管:"就是!你這個標題汪,這是又要搞事情呀!"github
我:「別急呀!這個jQ+canvas由於網上不少人博客都有寫,因此這邊只是附上一下jQ代碼供你們參考。下面纔是我今天要經過for循環代替上面的map()來實現的!!canvas
夫子:別淨扯理由,你是根本就不會map()用法!!」數組
老齊: "淨說什麼大實話!大棒是根本看不懂......"瀏覽器
我:.........好吧!大家說對了,個人確是不會map()方法。(讓我蹲牆角哭會/((╥╯^╰╥)」微信
好了不扯犢子了,言歸正傳。讓咱們回到下面要講的代碼上面來。dom
1.一、HTML骨架部分字體
<canvas id="hacker" width="500" height="500">請使用Google瀏覽器或者IE9以上</canvas>
1.二、JavaScript部分
var hacker = document.getElementById("hacker"); var width = hacker.width = screen.width; //screen.width拿到是當前屏幕寬度 var height = hacker.height; var ctx = haceker.getContext('2d');
作完這幾步以後,咱們就可以拿到當前屏幕的寬度、以及canvas畫布的寬度和獲得canvas畫布的上下文。
var num = Math.ceil(width / 10); var y = Array(num).join(0).split('');
這裏估計有人會詢問了,這裏建立一個數組是幹嗎。爲何數組的length >= num?
O(∩_∩)O哈哈~,彆着急,後面的代碼就會個你們逐一解釋了。
var draw = function() { ctx.fillStyle = 'rgba(0,0,0,.05)'; //創意核心語句之一 ctx.fillRect(0, 0, width, height); ctx.fillStyle = '#0f0'; ctx.font = '10px Microsoft YaHei'; for(i = 0; i < y.length; i++) { var x = (i * 10) + 10; text = String.fromCharCode(1e2 + Math.random() * 33); var y1 = y[i]; ke.getContext('2d').fillText(text, x, y1); console.log(height); if(y1 > Math.random() * 10 * height) { y[i] = 0; } else { y[i] = parseInt(y[i]) + 10; } } }
3.一、ctx繪畫過程解釋
ctx.fillStyle = 'rgba(0,0,0,.05)'; //創意核心語句之一 ctx.fillRect(0, 0, width, height);
這裏爲設定的區域鋪上一個rgba(0,0,0,.05) 這樣黑色半透明的背景。
ctx.fillStyle = '#0f0'; ctx.font = '10px Microsoft YaHei';
這裏就是畫出大小爲 10px,字體爲微軟雅黑的字體。
兩行代碼看起來就是很普通的代碼,可是組合起來卻發生一個質的變化。
爲何會有層次感呢?要知道getContext('2d')這句語句,就決定了canvas只能繪製2D圖像,不能繪製3D層次感的圖形!
答案就在 ctx.fillStyle = 'rgba(0,0,0,.05)';
上面,當重複調用方法的時候,這種半透明的灰黑色背景就會蓋在以前的畫好綠色文字上面。所以所以就形成了有文字是綠色,有的文字變成灰綠色。
各個文字之間造成一種視覺差,從而讓人感受到3D立體矩形代碼陣效果。因此當我發現兩組這麼普通的代碼組合起發生如此厲害效果,立即激動拍了拍鍵盤。大呼一聲!
「哇靠!這個真心666!」
3.二、for循環解釋
for(i = 0; i < num; i++) { var x = (i * 10) + 10; text = String.fromCharCode(65 + Math.random() * 62); var y1 = y[i]; ctx.fillText(text, x, y1); console.log(height); if(y1 > Math.random() * 10 * height) { y[i] = 0; } else { y[i] = parseInt(y[i]) + 10; } } }
3.三、關於canvasX軸上面文字控制
由於前面每次畫的文字大小都是10px,那麼若是我把canvasX軸平鋪滿。須要多少個文字呢。
答案 = Math.ceil(width / 10);
=> 即就是我前面的num
爲何得用Math.ceil()向上取整,而不能用Math.floor向下取整,parseInt()之類。
由於假設num = 300.8樣子,那麼使用Math.floor() 或者parseInt(),就好把這個數轉換成300
那麼後面,繪製300個文字在canvasX軸,那麼最右邊就還有0.8個文字,也就是8px空隙一種沒有字母出現。向上取整,就會鋪滿,多的部分超出canvas區域,就會消失。
text = String.fromCharCode(65 + Math.random() * 62);
這裏就是每次for循環的時候產生65 - 127 的數字,以後將其轉換爲大寫、小寫字母,以及一些符號
3.4關於canvasY軸的控制
這裏前面定義的數組就派上用場了var y = Array(num).join(0).split('');
,這裏就是用於記錄與控制每一次canvas文字的Y軸。
爲何要用數組去記錄呢?說實話,當初我也是這麼認爲的,因此我沒有嘗試控制每個文字Y軸的數據,讓因此的Y軸依次累加,結果效果以下:
因此以後我就奇思妙想,讓每次文字是排列X軸平鋪數字隨機呈現。例如第一次平鋪300個,第二次平鋪100個,第三次平鋪200.......,可是我仍是錯了:
因此屢次失敗的嘗試以後,發現仍是得控制利用一個數組控記錄與控制每個數字Y軸的數據。
Run(); function Run() { Game_Interval = setInterval(draw, 30); }
以後設置一個定時器,每次間隔30ms調用一次,而後大功告成。一個炫酷的黑客帝國矩形雨效果就出來了。
固然前面JavaScript代碼可能太凌亂,因此這邊就把JavaScript的所有呈上:
window.onload = function() { var kacker = document.getElementById("hacker"); var width = hacker.width = screen.width; var height = kacker.height; var ctx = hacker.getContext('2d'); var num = Math.ceil(width / 10); var y = Array(num).join(0).split(''); var draw = function() { ctx.fillStyle = 'rgba(0,0,0,.05)'; ctx.fillRect(0, 0, width, height); ctx.fillStyle = '#0f0'; ctx.font = '10px Microsoft YaHei'; for(i = 0; i < num; i++) { var x = (i * 10) + 10; text = String.fromCharCode(65 + Math.random() * 62); //console.log(text); 用來檢測 text 的值 var y1 = y[i]; ctx.fillText(text, x, y1); if(y1 > Math.random() * 10 * height) { y[i] = 0; } else { y[i] = parseInt(y[i]) + 10; } } } Run(); function Run() { Game_Interval = setInterval(draw, 100); } }
看到這裏不要覺得代碼就此結束了,好好吸取那個for循環以後。接下來再返回上面看一下map()方法,相信map()方法的用法是否是一會兒清晰明瞭。一舉兩得,既實現了5毛的特效,又幫助熟悉了一個map()方法用法.
效果預覽:黑客帝國矩形陣
(ps:效果圖掛在阿里雲上面,部分平臺點擊進去可能會有提示,例如微信,請忽略.....)
對於裏面完整blogDemo代碼感興趣的,能夠從本人github上閱覽。
源碼demo傳送門地址
我是車大棒,深藏功與名!(滑稽臉)