zoukankan      html  css  js  c++  java
  • 车大棒浅谈for循环+canvas实现黑客帝国矩形阵

    背景:
    一日在网上闲逛的之时,突然看到一个利用JQ插件实现canvas实现的电影黑客帝国的小Demo。觉得创意不错,就下载下来研究一下。

    黑客帝国开场动画效果Demo

    网上浏览jQuery的写法

    $(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进行绘画处理。要是让我这种段子手来写,估计我把敲烂键盘都想不出这样营造效果。艺术细胞真的很重要咕~~(╯﹏╰)

    老王:“等等大棒!不是说js+canvas实现黑客帝国矩形雨,可是你这个附上的代码分明是jQ+canvas.

    老管:"就是!你这个标题汪,这是又要搞事情呀!"

    我:“别急呀!这个jQ+canvas因为网上很多人博客都有写,所以这边只是附上一下jQ代码供大家参考。下面才是我今天要通过for循环代替上面的map()来实现的!!

    夫子:别净扯理由,你是根本就不会map()用法!!”

    老齐: "净说什么大实话!大棒是根本看不懂......"

    我:.........好吧!你们说对了,我的确是不会map()方法。(让我蹲墙角哭会/((╥╯^╰╥)

    你们开心就好

    万能for循环的写法

    好了不扯犊子了,言归正传。让我们回到下面要讲的代码上面来。

    1、基本准备工作

    1.1、HTML骨架部分

    <canvas id="hacker" width="500" height="500">请使用Google浏览器或者IE9以上</canvas>
    

    1.2、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画布的上下文。

    2、数组的准备
    var num = Math.ceil(width / 10);
    var y = Array(num).join(0).split('');
    

    这里估计有人会询问了,这里创建一个数组是干嘛。为什么数组的length >= num?

    O(∩_∩)O哈哈~,别着急,后面的代码就会个大家逐一解释了。

    不要激动,先安静的当一个美男子!

    不要激动,先安静的当一个美男子!

    3、定义一个重复调用核心draw()方法
        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.1、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.2、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.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 的数字,之后将其转换为大写、小写字母,以及一些符号

    控制台检测text

    3.4关于canvasY轴的控制

    这里前面定义的数组就派上用场了var y = Array(num).join(0).split('');,这里就是用于记录与控制每一次canvas文字的Y轴。

    为什么要用数组去记录呢?说实话,当初我也是这么认为的,所以我没有尝试控制每一个文字Y轴的数据,让所以的Y轴依次累加,结果效果如下:

    让所有的文字共用Y轴,然后依次累加

    所以之后我就奇思妙想,让每次文字是排列X轴平铺数字随机呈现。例如第一次平铺300个,第二次平铺100个,第三次平铺200.......,但是我还是错了:

    让X轴随机平铺数量

    错误的代码示范:

    失败的代码尝试

    所以多次失败的尝试之后,发现还是得控制利用一个数组控记录与控制每一个数字Y轴的数据。

    用Y轴分配每一个X轴点之后,后面产生如此的效果

    4、代码的收尾
    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传送门地址

    动次!打次!铛!

    动次!打次!铛!
    我是车大棒,深藏功与名!(滑稽脸)

  • 相关阅读:
    Github
    Vocabulary in Computer
    js中三种定义变量的方式const, var, let的区别
    Node.js-1
    JSON_in_js
    JSON快速入门
    Mysql tinyint长度为1时在java中被转化成boolean型
    maven上解决循环依赖、又不想新加第三模块的方法
    关于springboot和tomcat的服务能力做下简单的测试
    tomcat各个端口的作用
  • 原文地址:https://www.cnblogs.com/chedabang/p/6291504.html
Copyright © 2011-2022 走看看