Created
June 22, 2019 07:32
-
-
Save re4388/8cdad88e4658d565212d6e92e276d5ec to your computer and use it in GitHub Desktop.
Matrix digital rain (animated version)
This file contains 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 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 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
cooool effect saw on codepan