https://codepen.io/yuanchuan/pen/YoqWeR https://codepen.io/Kseso/pen/meGxxZ <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>黑客雨</title> <style type="text/css"> 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> </body> <script type="text/javascript"> 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> </html> 提示:你可以先修改部分代码再运行。 转载请注明:有爱前端 » 黑客雨 喜欢 (0)or分享 (0)