当前位置: 首页 > Web前端 > JavaScript

为什么你的代码下雨了?

时间:2023-03-26 21:50:52 JavaScript

大多数程序员都会有自己的个人网站,我们想要在自己的网站下描述一个很酷的背景,我们可能会用一些很酷的图片,或者叠加一个视频背景,或者是通过css3手工绘制。这些解决方案各有优缺点。canvas出现后,我们有了新的可能。我们可以通过canvas画出一些很酷的背景。有趣的是,我们还可以使用鼠标或者键盘事件与之进行交互,这样我们就有了绘制动态背景的能力。什么是画布?其实是Html5中的一个新标签。翻译过来就是canvas的意思。它是开发人员需要手动绘制的画布。我们怎么画呢?很明显,作为标签,能力有限,需要用javascript来处理绘制,所以我们很好理解canvas是纸,JavaScript是笔,通过二。我们平时使用的网页截图、H5游戏、前端动画效果、可视化图表……都有canvas的应用场景,所以它的功能特别强大,它的很多工作都是在GPU中进行的。一般来说性能非常高。对于我们做一些对性能要求比较高的场景来说是一个不错的选择。当然,这次我们不是来讲解canvas的,这里就不做过多讲解了。接下来我们来实战。实战的完整代码已放在文末,大家可以直接通过代码上的掘金观看。下面详细说说它的实现思路和过程,一步步拆解。看完之后,相信你也能轻松画出这样的效果。1.基本准备当然,最基本的是我们需要一个canvas标签,所以第一步就是创建一个标签,并为其绑定一个id属性,以便JavaScript可以获取到。有了标签之后,我们需要做什么?总结就是这些部分,获取canvas节点,获取窗口的宽高,给canvas设置宽高,同时获取它绘制的context对象,我们需要在里面调用各种api方法它来操作它。/*1.获取节点*/constcanvas=document.getElementById('app')/*2.设置canvas的宽高*/({innerWidth:cvs.width,innerHeight:cvs.height}=window);/*3.获取画布绘图上下文对象*/constctx=cvs.getContext('2d');其次,我们渲染的是不同的文本,所以我们定义了需要渲染哪些文本,同时每次渲染的时候随机获取一个,所以,我们写了一个每次随机获取一个文本的方法。/*4.准备一个获取随机文本的方法*/functiongetRandomChar(){conststr='YYDS'returnstr[Math.floor(Math.random()*str.length)]}我们希望的颜色每次绘制的文字也是不同的颜色,所以我们需要准备一个获取随机颜色的方法,相信这里很简单。/*5.准备一个获取随机颜色的方法*/functiongetRandomColor(){constcolors=['#33B5E5','#0099CC','#AA66CC','#9933CC','#669900','#FFBB33','#FF8800','#FF4444','#CC0000']returncolors[Math.floor(Math.random()*colors.length)]}有了这些准备,让我们进入核心绘制流程,我们继续2.绘图过程通过前面的步骤,我们已经准备了一些基本的工具和方法。让我们开始画吧。在此之前,我们需要考虑一下我们应该做什么。我们来看看这个简单的从图上来理解,如果我们实现这样的效果,最基本的就是我们需要的东西。我们可以想到的是,在基本的场景中,我们一行可能需要这么多。要达到上面的效果,我们只需要将屏幕覆盖起来,让它们的y点按不同的顺序排列即可。那么对于基本的列,我们需要什么东西,首先我们要定义一个列需要多宽,其次我们可以通过窗口/列的宽度知道一行可以放多少列宽度,其次,我们需要知道每一列的(x,y)点坐标,因为我们画的是整个窗口,坐标是从左上角(0,0)算起的。显然,在第一行的情况下,所有的y坐标是怎么计算出来的呢?第一列的y是一个字体高度,第二列是二等等,但是x的坐标也很简单,就是一列的宽度*你在哪一列,我们可以很容易的算出第一列的(x,y),然后我们让第一列绘制出来,我们在代码中会有详细的注释。/*6.设置列宽,计算一行需要多少列*/constcolumnWidth=30;constcolumnCount=Math.floor(window.innerWidth/columnWidth)我们定义一列为30,计算一列最多可以有columnCoun列,所以我们开始绘制,只需要循环columnCoun次就可以绘制一整行字符。同时,这里我们确定它的(x,y)坐标,开始绘制第一行:/*7.开始绘制*/functiondraw(){/*定义字体大小,以及每行需要的高度y坐标的线是字体的高度size*/constfontsize=16;/*获取字体绘制的随机颜色*/ctx.fillStyle=getRandomColor();/*设置字体格式和字体大小,可以自己设置*/ctx.font=`${fontsize}px"MicrosoftYaHei"`;/*循环多次列,每次计算xy的坐标,因为是第一行,所以y默认为1*字体高度*/for(leti=0;idraw()},40)这样,我们重复调用多次,或者写一个定时器,每秒调用一次drwa函数,按顺序绘制多列:最终实现如下效果如图,我们现在可以绘制多列Listed,但是发现到了底部之后,他就回不去起点了,还是一直往下执行。显然,我们需要判断当y坐标的高度大于窗口的高度时,我们需要让columnNextIndexs当前列恢复到初始值1,然后重新从顶部开始渲染,所以我们加入判断:if(y>window.innerHeight){columnNextIndexs[i]=1}加入判断后,我们可以在触底后,继续返回顶部,但是现在发现,返回顶部后,我们将覆盖最后一个文本,这与文章的开头不一样。然后绘制的文本消失。我们可以做些什么来让绘制的文字消失呢?我们可以给ctx设置一个半透明的背景色,并填满屏幕,这样每往回走一次,前面的文字就会变得越来越透明。在drwa开头放上下面两行代码就可以实现这个效果,ctx.fillStyle=`rgba(0,0,0,0.1)`;ctx.fillRect(0,0,window.innerWidth,window.innerHeight)设置好之后,我们就有了这样的效果,我们开始的效果好像只是最后一步。我们只需要更改不同列之间的高度差即可。要改变这个差值,我们只需要改变columnNextIndexs中每一项的值,让它们不是同一个值,就会出现高度差,怎么改变,我们在绘制完成后用++,那么我们只需要让它们到达底部的时候,加上一个判断即可。当他触底并且Math.random()>0.9时,我们让他回到顶部。由于随机数的不确定性,当他见底的时候,不同的柱子之间回到顶部的时间是不一样的,达到了我们初步的效果。下面看具体实现/*7.开始绘制*/functiondraw(){ctx.fillStyle=`rgba(0,0,0,0.1)`;ctx.fillRect(0,0,window.innerWidth,window.innerHeight)constfontsize=16;ctx.fillStyle=getRandomColor();ctx.font=`${fontsize}px"微软雅黑"`;for(leti=0;iwindow.innerHeight&&Math.random()>.9)returncolumnNextIndexs[i]=1ctx.fillText(getRandomChar(),x,y)columnNextIndexs[i]++}}至此代码雨的效果和实现思路就完成了,可以做很多好玩的事情了根据这个思路你还可以通过调整文字的内容,文字的大小,文字的间距,文字的背景等来改变,最后就可以实现一个属于自己的特殊背景图了,把它放在你的网站上有背景图片是不是很酷?最后,不要忘记你需要使用setInterval来连续调用draw()方法。当然,速度也由你控制。为了让这个Demo更好玩,我在里面加了一点交互,大家可以在代码上挖金了,大家上网体验一下,说说它的实现思路:添加实时自定义代码雨雨内容首先,我们绘制的text是我们自己提供的一个字符串,我们在里面放了一个输入框,以后可以修改它的内容,可以实时修改代码的内容,因为它会在每次绘制前调用随机读取的text,所以我们只需要将读取的文本内容更改为从我们下次输入的新输入中读取到的文本内容,以便将文本排列得井井有条。我们默认按顺序排列文本,因为文本是随机获取的,但是当我们看到我们的封面图片时,我们发现我们实际上是有序的。我们如何实现这个功能呢?那么很明显我们在获取文本的时候需要按顺序返回文本,但是不同列的顺序是不同的,需要参考不同列高度差的初始形式,定义一个数组来记录所有的currentcolumns的绘制次数,这样才能让文字井井有条,可以让它看起来更有趣。大家可以想想更多有趣的事情。。。在线体验结合了以上所有内容,这里是完整版代码,快来体验吧,在线体验地址:完整代码