JS實現《黑客帝國》字符雨飄落特效

此段代碼通過Canvas元素實現了電影《黑客帝國》中進入Matrix的終端界面的一個動畫效果。
兼容H5和各種版本的瀏覽器。可以在這裏看到線上效果,點我,點我!
在瀏覽器中打開,配上F11全屏效果,效果棒棒的!
請在這裏輸入圖片描述
在代碼的起始部分,使用了一個兼容低版本瀏覽器的requestAnimationFrame的方法。也能提高瀏覽器的性能。
代碼裏有5個技巧,
1、var clearColor = ‘rgba(0, 0, 0, .1)’;
ctx.fillStyle = clearColor;
ctx.fillRect(0, 0, w, h);
此段代碼在每次循環的時候繪製了一個0.1透明度的蒙層,一次次的覆蓋,在字符下落的時候,留下一段陰影效果。
2、context.fillText(text, i * font_size, drops[i] * font_size);
通過此段代碼在一次循環中繪製出整屏的字符,通過i的增加變更列,通過drops[i],變更每列的行。通過drops[i]最初形成是依據高度隨機的,第二屏之後都是從0起始。
3、ctx.translate(w, 0);
ctx.scale(-1, 1);
通過翻轉畫布,造成字符翻轉的效果,給人一種神祕感。原電影中的日文都是翻轉後的。
4、Math.random() > 0.95;
可以使每列字符消失的時間隨機,這樣重新生成的時間也隨機了,形成字符參差不齊的效果。

5、words字符串可以依據需要修改,全是日文平假名感覺更真實。

<canvas id="canvas" style="background:#000;"></canvas>
<script>
//兼容低版本瀏覽器的requestAnimationFrame;
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}());


window.onload = function(){
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
w, h;
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;


// 初始化
var wordColor = "#33ff33", 
words = "0123456789qwertyuiopasdfghjklzxcvbnm,./;'\[]QWERTYUIOP{}ASDFGHJHJKL:ZXCVBBNM<>?がガぎギぐグげゲごゴきゃキャきゅキュきょキョりゃリャゅリュりょリョ",
wordsArr = words.split(''), 
font_size = 16,  
clumns = parseInt(w / font_size, 10) , //瀏覽器寬除以字符寬得列數
drops = []; //存儲每列的起始位置


for(var i=0; i<clumns; i++){
// 隨機的起始位置
drops[i] = Math.floor(Math.random() * h);
}

// 繪製
function draw(time){
ctx.save();


// 水平翻轉畫布
ctx.translate(w, 0);
ctx.scale(-1, 1);

// 填充字符
ctx.fillStyle = wordColor;
ctx.font = font_size + "px arial";
for (var i = 0; i < drops.length; i++){
var text = wordsArr[Math.floor(Math.random() * wordsArr.length)];
ctx.fillText(text, i * font_size, drops[i] * font_size);
// 0.95的隨機數造成列消失的時間不一致,產生的列也隨之改變
if (drops[i] * font_size > h && Math.random() > 0.95){
drops[i] = 0;
}
drops[i]++;
}
ctx.restore();
}


//循環
var clearColor = 'rgba(0, 0, 0, .1)', //每次循環加0.1透明的蒙層
lt = 0,
speed = 50; // 字體下落速度
function drawFrame(time){
if(time - lt > speed) {
lt = time;
ctx.fillStyle = clearColor;
ctx.fillRect(0, 0, w, h);
draw();
}
window.requestAnimationFrame(drawFrame, canvas);
}
window.requestAnimationFrame(drawFrame, canvas);

//瀏覽器縮放
function resize(){
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
}
canvas.addEventListener("resize", resize);
        // 綁定F11全屏事件,由於全屏事件在部分瀏覽器中不會觸發resize,和無法通過F11捕捉到fullscreenchange事件,於是用F11的keyup替代。感謝boyipiao童鞋的反饋~
        document.addEventListener('keyup', function(event) {
var code = event.keyCode || event.which;
 if(code == 122){
resize();
}
},false);
}
</script>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章