Created
August 3, 2019 05:16
-
-
Save yehaifeng/837e16c51c161eda0a6aaa3e04bbf7db to your computer and use it in GitHub Desktop.
Matrix digital rain (animated version)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<main></main> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment