js 实现代码雨功能
首先来看一下效果:
这里是使用了canvas来绘制出来的,但是canvas是静态的,如何实现动态的下雨效果呢?没错,定时器,都是基本的东西,但是组合起来效果还是很好的。
下面开始方法:
第一步是需要获取展示代码雨的dom宽高
这里是用的全屏,所以宽高就直接是windom的innerWidth和innerHeight
const cvs = document.getElementById("app")
const state = {
str: "01",
width: null,//窗口宽度
height: null,//窗口高度
ctx: null,//canvas上下文
columnWidth: 20,//一列文字宽度
columnCount: 0,//计算总共可以放下多少列文字
columnNextIndexs: [],//记录每一列文字当前的文字应该是哪个
timer: null//定时器
}
//获取窗口宽高 state.width = window.innerWidth; state.height = window.innerHeight;
//然后赋值给canvas
({ innerWidth: cvs.width, innerHeight: cvs.height } = window);
第二步计算列数
//计算一共可以多少列 state.columnWidth = 25; state.columnCount = Math.floor(window.innerWidth / state.columnWidth);
//初始化所有列文字的位置为1
state.columnNextIndexs = new Array(state.columnCount).fill(1);
/* 也可以初始化给点随机值 可以在第一次的时候有高度差异 */
// state.columnNextIndexs.forEach((_, i) => state.columnNextIndexs[i] = Math.floor(Math.random() * state.columnCount));
第三步获取随机文字与随机颜色
/* 获取随机颜色 */ function getRandomColor() { var r = Math.floor(Math.random() * 256); var g = Math.floor(Math.random() * 256); var b = Math.floor(Math.random() * 256); return "rgb(" + r + "," + g + "," + b + ")"; } /* 获取随机文字 */ function getRandomChar() { return state.str[Math.floor(Math.random() * state.str.length)] }
接着就是绘制了,如何实现字符渐变的效果,就是通过绘制的时候添加一层有透明度的遮罩,每次绘制都加一层,这样原本绘制的跟新绘制的字符就是产生颜色差
function draw() { const { ctx, width, height, columnWidth, columnCount, columnNextIndexs } = state ctx.fillStyle = `rgba(0, 0, 0, 0.1)`;//遮罩 ctx.fillRect(0, 0, width, height) const fontsize = 16; ctx.fillStyle = getRandomColor(); ctx.font = `${fontsize}px "Microsoft YaHei"`; for (let i = 0; i < columnCount; i++) { const x = i * columnWidth; const y = 20 * columnNextIndexs[i]; ctx.fillText(getRandomChar(i), x, y);
//当绘制的文字高度超过dom的高度时,重置位置为0,从头开始 或者随机数大于0.99时从头开始绘制,这样可以使每一列产生位差 if (y > height && Math.random() > .99) { columnNextIndexs[i] = 0 } else { //记录每列写到的文字,累计++ columnNextIndexs[i]++ } } }
/* 开始执行绘画 */
function startDraw() {
initCalcSize()
state.timer = setInterval(() => {
draw()
}, 40);
}
/* 重新开始绘画 */
function againDraw() {
clearInterval(state.timer)
startDraw()
}
/* 窗口尺寸改变 重新开始绘制 */
window.onresize = () => againDraw()
到此,代码雨的效果就可以展示了