I was really curious about implementing the Matrix Digital Rain effect and looked at many implementations.
The best implementation I saw was Digital Rain by javascriptacademy.
I think the others were a little overly complicated.
Naturally, I had to code golf it and make it work in an address bar:
data:text/html,<body style=overflow:hidden;margin:0 onload="x=c.getContext`2d`;j=l=>x.fillStyle=l;r=Math.random;c.width=w=innerWidth;c.height=h=innerHeight;p=[];f=20;x.font=f+'px A';setInterval(`j('rgba(0,0,0,.05)');x.fillRect(0,0,w,h);j('lime');for(i=1e3;i--;){x.fillText(String.fromCharCode(r()*93+33),i*f,y=(p[i]=p[i]||1)*f);p[i]=y>h&&r()>.98?0:y/f+1}`,f)"><canvas id=c>This snippet of code also displays words randomly with the digital rain in white.
To have random words appear on screen, replace PUT,RANDOM,WORDS,HERE with words of your own. This also resizes the canvas when the screen resizes.
Because the code has gotten bigger, I went ahead and just added those other features including a black background.
data:text/html,<body bgcolor=🔥 style=overflow:hidden;margin:0 onload="a='PUT,RANDOM,WORDS,HERE'.split`,`;b='';f=30;x=c.getContext`2d`;j=l=>x.fillStyle=l;r=Math.random;z=()=>{c.width=w=innerWidth;c.height=h=innerHeight;d=~~(w/f);x.font=f+'px monospace'};z();onresize=z;p=[];setInterval(`j('rgba(0,0,0,.05)');x.fillRect(0,0,w,h);for(i=0;i<d;i++){if(!b){g=~~(r()*(d-1))+1;b=a[~~(r()*a.length)];}j(g&&g==i?'white':'lime');x.fillText(g&&g==i?b.charAt(0):String.fromCharCode(r()*93+33),i*f,y=(p[i]=p[i]||1)*f);if(g&&g==i)b=b?b.substr(1):0;p[i]=y>h&&r()>.98?0:y/f+1}`,f)"><canvas id=c>- The address bar does not like certain character which need to use its proper URL Encode version.
#needs to be%23%needs to be%25
- The equivalent of
#0F0became%230F0so usinglimeused less characters. - Using unescaped special characters gives no error messages. Just a blank screen, which is terribly hard to debug.
Use this code to display the char codes. Using char codes helps save on characters used in your code.
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const randChar = letters.charAt(Math.random() * letters.length);vs
const randChar = String.fromCharCode(Math.random() * 25 + 65);The 2nd implementation uses less code and has the potential to use other and larger character sets.
- Chess Pieces: 9812 + 11
- Card Suits: 9824 + 8
- Music Notes: 9833 + 7
- Stars: 10022 + 37
Run this code to display the list of code values.
<table width="100%"><tbody><tr id=o></tr></tbody></table>
<script>
const showFromChar = (c, count) => new Array(count).fill().map((_, i) => {
const startCode = c.codePointAt();
const code = startCode + i;
return `${i}-` + String.fromCodePoint(code) + ` (${code})`;
}).join`<br>`;
o.innerHTML = ['ア', 'あ', 'A', 'a', '0', '😀', 'ㄴ'].map(s => `<td valign="top">${showFromChar(s, 100)}</td>`).join``;
</script>- 48-58 (10 chars) Numbers (0-9)
- 65-90 (26 chars) Capital Letters (A-Z)
- 97-122 (26 chars) Lowercase Letters (a-z)
- 12354 (84 chars) Hiragana
- 12450 (88 chars) Katakana
- 128512 (68 chars) Emoji Faces 😀
- 128512 (88 chars) Korean
- 35830 (??? chars) Chinese (I put in 999 and saw more characters)
Display character set
<p id=o></p>
<script>
const getCharSet = (start, count) => (
new Array(count).fill().map((_, i) => String.fromCodePoint(start + count))
);
//displays Katanaka set
o.innerHTML = getCharSet(12450, 88).join`<br>`;
</script>'A'.codePointAt()`
returns 65String.fromCharCode(65)
returns 'A'
String.fromCodePoint(65)
returns 'A'The difference between the two is that fromCharCode doesn't work with emojis. So You should use codePointAt and fromCodePoint.
Hiragana Version
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=20;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){x.fillText(String.fromCharCode(~~(r()*84)+12354),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,60)"><canvas id=c><style>body{overflow:hidden;margin:0}Katakana Version
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=20;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){x.fillText(String.fromCharCode(r()*88+12450),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,20)"><canvas id=c><style>body{overflow:hidden;margin:0}Emoji Version
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=20;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){x.fillText(String.fromCodePoint(~~(r()*68)+128512),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,60)"><canvas id=c><style>body{overflow:hidden;margin:0}Korean Version
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=20;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){x.fillText(String.fromCodePoint(~~(r()*88)+12596),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,60)"><canvas id=c><style>body{overflow:hidden;margin:0}Chinese Version
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=20;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){x.fillText(String.fromCodePoint(~~(r()*999)+35830),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,60)"><canvas id=c><style>body{overflow:hidden;margin:0}Vehicles
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=20;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){x.fillText(String.fromCodePoint(~~(r()*36)+128640),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,20)"><canvas id=c><style>body{overflow:hidden;margin:0}Chess Pieces
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=30;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){x.fillText(String.fromCharCode(~~(r()*12)+9812),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,60)"><canvas id=c><style>body{overflow:hidden;margin:0}Card Suits
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=30;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){x.fillText(String.fromCharCode(~~(r()*8)+9824),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,60)"><canvas id=c><style>body{overflow:hidden;margin:0}Cards
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=50;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';b=new Array(86).fill(0).map((_,i)=>i+127136).filter(a=>![127151,127152,127168,127183,127184].includes(a));setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){
t=b[~~(r()*b.length)];x.fillText(String.fromCodePoint(t),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,60)"><canvas id=c><style>body{overflow:hidden;margin:0}Stars
data:text/html,<body onload="x=c.getContext`2d`;r=Math.random;c.width=innerWidth;c.height=innerHeight;f=30;n=~~(c.width/f);p=new Array(n).fill(1);x.font=f+'px monospace';setInterval(`x.fillStyle='rgba(0,0,0,0.05)';x.fillRect(0,0,c.width,c.height);x.fillStyle='lime';for(i=0;i<n;i++){x.fillText(String.fromCodePoint(~~(r()*38)+10022),i*f,p[i]*f);if(p[i]*f>c.height&&r()>.975)p[i]=0;p[i]++}`,60)"><canvas id=c><style>body{overflow:hidden;margin:0}