0%

模仿黑客帝国特效



介绍

点击这里查看效果:传送门

01代码动画+打字机效果,整合案例见博客个人简介应用,点这里看效果。

效果如下图,黑客电影里01字符掉落的效果。

动手制作

新建一个HTML文件。

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>qsdbl</title>
</head>
<body>

</body>
</html>

body

设置一下body的样式。背景颜色为黑色,溢出隐藏。

1
2
3
4
5
6
<style>
body{
background-color: #000000;
overflow: hidden;
}
</style>

绘制动画

开始绘制动画。在HTML文件的头部添加如下<canvas>标签,id名随意,宽高设置大一点避免有些设备过宽导致没有全屏显示。

1
<canvas id="myCanvas" width="2000px" height="1000px"></canvas>

script

下边代码在<script>标签内添加。且在页面加载完成后执行。

1
2
3
4
5
6
<script>
window.onload = function(){


}
</script>

首先我们定义几个变量,方便参数调节。

  • fontSize,字体大小
  • col_show,密集程度(其实是透明程度,绘制一层黑色区域遮挡旧字符时用于指定透明度。透明越低,旧字符显示的就越多,反之则越少)
  • c,Canvas元素
  • pen,绘制的画笔
  • num,计算显示的文字列数,并创建相应的数组(一列对应一个数组)

在进行绘制之前,我们需要确定打开HTML文件的设备是pc还是手机。从而指定不同的fontSize和col_show。(还可以使用CSS中的@media 查询来实现,具体使用方法参考该博客:传送门

1
2
3
4
5
6
7
8
var ua = navigator.userAgent.toLowerCase();
if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|ZTE/.test(navigator.userAgent)) || ua.match(/MicroMessenger/i) == "micromessenger"){
var fontSize = 70;//手机字体大小
var col_show = 0.07;//密集程度
}else{
var fontSize = 20;//pc字体大小
var col_show = 0.18;
}

设置一些变量值。设置Canvas元素。注意id名不要写错了。

1
2
3
4
5
let c = document.querySelector("#myCanvas");//获取Canvas元素
c.width = window.innerWidth;//获取窗口的文档显示区的宽度
c.height = window.innerHeight;//获取窗口的文档显示区的高度
let pen = c.getContext('2d');//getContext() 方法返回一个用于在画布上绘图的环境。参数指定了您想要在画布上绘制的类型(目前只支持2d)
let num = Array(parseInt(c.width/fontSize)).fill(0);//计算显示的文字列数(文字大小前边设置)。并创建相应的数组(一列对应一个数组),数组初始值设置为0

现在要让画面动起来。我们使用一个周期定时器,每60毫秒执行一次定义在其内部的函数。想要改变画面速度可以更改该参数。

1
2
3
4
setInterval(function (){


},60);//定时器让画面动了起来

在这个周期定时器内我们来绘制图像(周期性)。

首先绘制一层黑色,有一定透明度的图像。这个的作用主要是为了遮挡住前边绘制的01字符(在后边。这个是周期性的,要记住这点),营造一种字符掉落过程中慢慢消失的感觉,并遮挡住n个周期前绘制的字符。所以更改参数透明度col_show,可以更改显示字符的密集程度。

1
2
pen.fillStyle = "rgb(0,0,0,"+col_show+")";//画笔颜色,黑色,透明程度
pen.fillRect(0,0,c.width,c.height);//fillRect() 方法绘制"已填充"的矩形。默认的填充颜色是黑色。

绘制01字符前的准备工作。指定画笔颜色,字体大小等等参数。

1
2
pen.fillStyle = "#0f0" ;//设置或返回用于填充绘画的颜色、渐变或模式。(绿色)
pen.font = fontSize+"px Calibri";

现在绘制01字符。num为前边创建的数组,一列对应一个数组。使用forEach函数遍历每一个数组。forEach循环完之后,就会绘制出一行0、1字符。

  • ()=>{},是js中的箭头函数,可以理解为一个匿名函数。

    • y为forEach返回的数组值
    • i为forEach返回的数组索引。
  • pen.fillText(文本,x,y)用于绘制文本。

    • x坐标为:i*fontSize。索引值剩字体大小,
    • y坐标为:y(数组的值)
      • 第一次绘制时,数组值为0,即y坐标为0
      • 通过num[i] = Math.random()<0.05?0:y+fontSize;更改下一次绘制该数组对应的列时的y坐标(记住一次forEach绘制一行)。
      • 这是一个三目运算符,如果前边的条件成立则返回问号?后边的值否则返回冒号:后边的值。为什么不直接num[i] = y+fontSize;,主要是为了营造一种错落感。随机让该列的字符从头开始下落(y突然变成0,下一次绘制将会从头开始),可通过更改参数0.05改变从头开始的概率。
  • parseInt(Math.random()+0.5)用于获得0或1。可以通过更改参数0.5,改变0、1出现的概率。

1
2
3
4
5
num.forEach((y,i)=>{//forEach()函数,返回的数据为当前元素、当前元素的索引值、当前元素所属的数组对象。
//所以数组值(初始值为0) 对应 y ,数组索引 对应 i
pen.fillText(parseInt(Math.random()+0.5).toString(),i*fontSize,y);//fillText() 方法在画布上绘制填色的文本。文本的默认颜色是黑色。文本、x坐标、y坐标
num[i] = Math.random()<0.05?0:y+fontSize;//更改y坐标(增加随机数是为了产生错落感)
})

至此全部的代码都完成了。下边是全部代码整合:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html>
<head>
<canvas id="myCanvas" width="2000px" height="1000px"></canvas>
<meta charset="utf-8" />
<title>qsdbl</title>
</head>
<body>

</body>
<style>
body {
background-color: #000000;
overflow: hidden;
}
</style>
<script>
window.onload = function() {
var ua = navigator.userAgent.toLowerCase();
if (/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (
/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|ZTE/
.test(navigator.userAgent)) || ua.match(/MicroMessenger/i) == "micromessenger") {
var fontSize = 70; //手机字体大小
var col_show = 0.07; //密集程度
} else {
var fontSize = 20; //pc字体大小
var col_show = 0.18;
}
let c = document.querySelector("#myCanvas"); //获取Canvas元素
c.width = window.innerWidth; //获取窗口的文档显示区的宽度
c.height = window.innerHeight; //获取窗口的文档显示区的高度
let pen = c.getContext('2d'); //getContext() 方法返回一个用于在画布上绘图的环境。参数指定了您想要在画布上绘制的类型(目前只支持2d)
let num = Array(parseInt(c.width / fontSize)).fill(0); //计算显示的文字列数(文字大小前边设置)。并创建相应的数组(一列对应一个数组),数组初始值设置为0
setInterval(function() {
pen.fillStyle = "rgb(0,0,0," + col_show + ")"; //画笔颜色,黑色,透明程度
pen.fillRect(0, 0, c.width, c.height); //fillRect() 方法绘制"已填充"的矩形。默认的填充颜色是黑色。
pen.fillStyle = "#0f0"; //设置或返回用于填充绘画的颜色、渐变或模式。(绿色)
pen.font = fontSize + "px Calibri";
num.forEach((y, i) => { //forEach()函数,返回的数据为当前元素、当前元素的索引值、当前元素所属的数组对象。
//所以数组值(初始值为0) 对应 y ,数组索引 对应 i
pen.fillText(parseInt(Math.random() + 0.5).toString(), i * fontSize, y); //fillText() 方法在画布上绘制填色的文本。文本的默认颜色是黑色。文本、x坐标、y坐标
num[i] = Math.random() < 0.05 ? 0 : y + fontSize; //更改y坐标(增加随机数是为了产生错落感)
})
}, 60); //定时器让画面动了起来
}
</script>
</html>
若图片不能正常显示,请在浏览器中打开

欢迎关注我的其它发布渠道