用html实现文字雨

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>文字雨</title>
  <style>
    html, body { 
      height: 100%; 
      margin: 0; 
      overflow: hidden;
    }
    body { 
      display: flex; 
      align-items: center; 
      justify-content: center;
      background: #000; 
    }
    main {
      display: flex;
    }
    p {
      line-height: 1;
    }
    span {
      display: block;
      width: 2vmax; 
      height: 2vmax; 
      font-size: 2vmax; 
      color: #9bff9b11;
      text-align: center;
      font-family: "Helvetica Neue", Helvetica, sans-serif;
    }
  </style>
</head>
<body>
  <main></main>
  <script>
    function r(from, to) {
      return ~~(Math.random() * (to - from + 1) + from);
    }
    function pick() {
      return arguments[r(0, arguments.length - 1)];
    }
    function getChar() {
      return String.fromCharCode(pick(
        r(0x3041, 0x30ff),
        r(0x2000, 0x206f),
        r(0x0020, 0x003f)
      ));
    }
    function loop(fn, delay) {
      let stamp = Date.now();
      function _loop() {
        if (Date.now() - stamp >= delay) {
          fn(); stamp = Date.now();
        }
        requestAnimationFrame(_loop);
      }
      requestAnimationFrame(_loop);
    }
    class Char {
      constructor() {
        this.element = document.createElement('span');
        this.mutate();
      }
      mutate() {
        this.element.textContent = getChar();
      }
    }
    class Trail {
      constructor(list = [], options) {
        this.list = list;
        this.options = Object.assign(
          { size: 10, offset: 0 }, options
        );
        this.body = [];
        this.move();
      }
      traverse(fn) {
        this.body.forEach((n, i) => {
          let last = (i == this.body.length - 1);
          if (n) fn(n, i, last);
        });
      }
      move() {
        this.body = [];
        let { offset, size } = this.options;
        for (let i = 0; i < size; ++i) {
          let item = this.list[offset + i - size + 1];
          this.body.push(item);
        }
        this.options.offset =
          (offset + 1) % (this.list.length + size - 1);
      }
    }
    class Rain {
      constructor({ target, row }) {
        this.element = document.createElement('p');
        this.build(row);
        if (target) {
          target.appendChild(this.element);
        }
        this.drop();
      }
      build(row = 20) {
        let root = document.createDocumentFragment();
        let chars = [];
        for (let i = 0; i < row; ++i) {
          let c = new Char();
          root.appendChild(c.element);
          chars.push(c);
          if (Math.random() < .5) {
            loop(() => c.mutate(), r(1e3, 5e3));
          }
        }
        this.trail = new Trail(chars, {
          size: r(10, 30), offset: r(0, 100)
        });
        this.element.appendChild(root);
      }
      drop() {
        let trail = this.trail;
        let len = trail.body.length;
        let delay = r(10, 100);
        loop(() => {
          trail.move();
          trail.traverse((c, i, last) => {
            c.element.style = `
        color: hsl(136, 100%, ${85 / len * (i + 1)}%)
      `;
            if (last) {
              c.mutate();
              c.element.style = `
          color: hsl(136, 100%, 85%);
          text-shadow:
            0 0 .5em #fff,
            0 0 .5em currentColor;
        `;
            }
          });
        }, delay);
      }
    }

    const main = document.querySelector('main');
    for (let i = 0; i < 50; ++i) {
      new Rain({ target: main, row: 50 });
    }
  </script>
</body>
</html>
相关推荐
金木讲编程7 分钟前
Claude、Agent与Copilot协作生成Angular应用
前端·ai编程
振华OPPO44 分钟前
Vue:“onMounted“ is defined but never used no-unused-vars
前端·javascript·css·vue.js·前端框架
欧雷殿1 小时前
在富阳银湖成立地域化的软件研发团队
前端·程序员·创业
狂炫冰美式2 小时前
前端实时推送 & WebSocket 面试题(2026版)
前端·http·面试
JefferyXZF2 小时前
新手建站零门槛!Vercel+Cloudflare+Namesilo域名购买部署全流程
前端
yinuo2 小时前
微信浏览器缓存机制大揭秘:为什么你总刷不出新页面?
前端
拉不动的猪2 小时前
try...catch 核心与生态协作全解析
前端·javascript·vue.js
Xeon_CC2 小时前
在react-app-rewired工程项目中,调试AntVG6库源码包。
前端·react.js·前端框架
o***Z4483 小时前
前端无障碍开发检查清单,WCAG合规
前端
J***Q2923 小时前
前端CSS架构模式,BEM与ITCSS
前端·css