用canvas画个代码雨玩玩

最终效果

实现原理

根据屏幕的宽度跟每一列的宽度,生成 x 列,然后添加到一个数组之中,由这个数组来控制每一列中每一行的的位置,再画完一行之后,使用canvas的api来擦除上一次渲染的行,这样就可以做到渐变下落的效果。然后再添加一点随机的逻辑,达到下落时机不同的效果。

实现过程

设置canvas,获取列数

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>代码雨</title>
</head>

<style>
    *{
        margin: 0;
        padding: 0;
    }
</style>

<body>
    <canvas id="canvas-container"></canvas>
</body>

<script type="text/javascript">
    const window_width = window.innerWidth
    const window_height = window.innerHeight
    const _canvas = document.getElementById('canvas-container')
    const _canvas_content = _canvas.getContext('2d')
    _canvas.width = window_width
    _canvas.height = window_height
    
    // 设置列宽 行高
    const column_w = 20
    const row_h  = 20
    
    // 总列数
    const columns = Math.floor(window_width/column_w)
    
</script>

</html>

从动图可以看见下落的东西其实是一些文本跟随机的颜色

html 复制代码
<script type="text/javascript">
...

const text = 'hello-word'

const random = (max,min) => Math.floor(Math.random() * (max -  min + 1))
const randomText = () => text[random(text.length - 1,0)] // 获取随机文本
const randomColor = () => ['#eaac00','#0088F7','#FE7D0D','#4DCBA7'][random(3,0)] // 设置随机的颜色

</script>

最后完善一些渲染的逻辑

html 复制代码
<script type="text/javascript">
...

// 由这个数组来控制每一列的渲染位置
const nextChar = new Array(columns).fill(0)

// 渲染函数
const draw = () => {

    // 擦一下画布
    _canvas_content.fillStyle = 'rgba(240,240,240,0.1)'
    _canvas_content.fillRect(0,0,window_width,window_height)
    
    
    // 循环渲染出画布的位置
    for (let i = 0; i < columns; i++) {
        // 颜色 位置
        _canvas_content.fillStyle = randomColor()
        const  char = randomText()
        const x = column_w * i
        const y = (nextChar[i] + 1) * row_h
        if (y > window_height && Math.random() > 0.9){
            nextChar[i] = 0
        }else{
            nextChar[i]++;
        }
        _canvas_content.fillText(char,x,y)
    }

}
</script>

以上代码,在if中添加了Math.random() > 0.9就是为了达到让代码下落的时候出现偏差,从而达到错落有致的效果。 这个时候调用一下draw(),如下图:

调用多几次的效果

最后再加个轮询,让他不停的调用draw函数就可以了

html 复制代码
<script type="text/javascript">
...

setInterval(() => {
 draw()
},50)

</script>

到此,大功告成。以下是完整代码

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>代码雨</title>
</head>

<style>
    *{
        margin: 0;
        padding: 0;
    }
</style>

<body>
    <canvas id="canvas-container"></canvas>
</body>

<script type="text/javascript">
    const window_width = window.innerWidth
    const window_height = window.innerHeight
    const _canvas = document.getElementById('canvas-container')
    const _canvas_content = _canvas.getContext('2d')
    _canvas.width = window_width
    _canvas.height = window_height

    const column_w = 20
    const row_h = 20
    const columns = Math.floor(window_width / column_w)

    const text = 'hello-word!'
    const random = (max,min) => {
       return Math.floor(Math.random() * (max -  min + 1))
    }

    const randomText = () => {
        return text[random(text.length - 1,0)]
    }

    const randomColor = () => {
        return  ['#eaac00','#0088F7','#FE7D0D','#4DCBA7'][random(3,0)]
    }

    const nextChar = new Array(columns).fill(0)
    console.log(nextChar,'nextChar')

    function draw() {
        _canvas_content.fillStyle = 'rgba(240,240,240,0.1)'
        _canvas_content.fillRect(0,0,window_width,window_height)
        for (let i = 0; i < columns; i++) {
            // 颜色 位置
            _canvas_content.fillStyle = randomColor()
            const  char = randomText()
            const x = column_w * i
            const y = (nextChar[i] + 1) * row_h
            if (y > window_height && Math.random() > 0.9){
                nextChar[i] = 0
            }else{
                nextChar[i]++;
            }
            _canvas_content.fillText(char,x,y)
        }
    }

    setInterval(() => {
     draw()
    },50)

</script>


</html>
相关推荐
Мартин.2 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。3 小时前
案例-表白墙简单实现
前端·javascript·css
数云界3 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd3 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常3 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer3 小时前
Vite:为什么选 Vite
前端
小御姐@stella3 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing3 小时前
【React】增量传输与渲染
前端·javascript·面试
eHackyd3 小时前
前端知识汇总(持续更新)
前端
万叶学编程6 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js