🧠 Description
Matrix News Reader is a cinematic, hacker-style UI inspired by The Matrix.
It combines a digital rain canvas animation with a terminal-like news reader that fetches live headlines from Reddit and types them on screen character by character.
This project is a perfect example of:
- Creative coding with Canvas
- Retro hacker aesthetics
- Real-time data visualization
- Typing & glitch-style UI effects
✨ Key Features
- 🟢 Matrix-style binary rain animation
- 📰 Live news fetched from Reddit
- ⌨️ Terminal-like typing effect
- ⚡ Smooth animation loop with FPS lock
- 🚨 Loading & error overlays
- 🖥️ Full-screen immersive UI
🧱 HTML Structure
Core HTML Layout
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Matrix News Reader</title>
7 <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700|Source+Code+Pro:200'>
8 <style>
9 html, body, canvas {
10 font-family: monospace;
11 background: #000;
12 width: 100%;
13 height: 100%;
14 margin: 0;
15 padding: 0;
16 overflow: hidden;
17 }
18
19 body > div, body canvas {
20 position: absolute;
21 top: 0;
22 bottom: 0;
23 left: 0;
24 right: 0;
25 }
26
27 canvas {
28 z-index: 10;
29 opacity: 0.8;
30 }
31
32 .flex {
33 display: flex !important;
34 }
35
36 .effects {
37 z-index: 100;
38 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAQAAAD41K0JAAAADklEQVQI12Ng+A+EQAQADfsC/pD7Z48AAAAASUVORK5CYII=);
39 background-repeat: repeat;
40 opacity: 0.1;
41 pointer-events: none;
42 }
43
44 .overlays {
45 z-index: 50;
46 display: flex;
47 justify-content: center;
48 align-items: center;
49 }
50
51 .overlays .loading, .overlays .error, .overlays .msgbox {
52 width: 400px;
53 height: 140px;
54 border: 7px solid;
55 display: none;
56 justify-content: center;
57 align-items: center;
58 font-family: "Ubuntu Mono";
59 font-weight: 600;
60 font-size: 55px;
61 letter-spacing: 5px;
62 animation: msgopen ease-in-out 0.4s forwards;
63 }
64
65 .overlays .loading {
66 color: #00e700;
67 border-color: rgba(0, 231, 0, 0.8);
68 background: rgba(0, 66, 0, 0.85);
69 text-shadow: 0 0 10px #00e700;
70 box-shadow: 0 0 20px rgba(0, 231, 0, 0.7);
71 }
72
73 .overlays .loading span {
74 animation: loadingblink 1.5s linear infinite;
75 }
76
77 .overlays .error {
78 color: #e70000;
79 border-color: rgba(231, 0, 0, 0.8);
80 background: rgba(66, 0, 0, 0.85);
81 text-shadow: 0 0 10px #e70000;
82 box-shadow: 0 0 20px rgba(231, 0, 0, 0.7);
83 }
84
85 .overlays .error span {
86 animation: errorblink 2s linear infinite;
87 }
88
89 .overlays .msgbox {
90 color: #d3ffd3;
91 border-color: rgba(211, 255, 211, 0.8);
92 background: rgba(45, 81, 45, 0.85);
93 text-shadow: 0 0 10px rgba(211, 255, 211, 0.8);
94 box-shadow: 0 0 20px rgba(211, 255, 211, 0.5);
95 width: 500px;
96 height: auto;
97 min-height: 50px;
98 padding: 20px 25px;
99 font-weight: 400;
100 font-size: 24px;
101 line-height: 40px;
102 letter-spacing: initial;
103 overflow: hidden;
104 }
105
106 .overlays .msgbox span {
107 word-wrap: break-word;
108 position: relative;
109 }
110
111 @keyframes loadingblink {
112 0%, 100% {
113 color: rgba(0, 231, 0, 0.6);
114 text-shadow: 0 0 6px rgba(0, 231, 0, 0.6);
115 }
116 50% {
117 color: #00e700;
118 text-shadow: 0 0 10px #00e700;
119 }
120 }
121
122 @keyframes errorblink {
123 0%, 100% {
124 color: rgba(231, 0, 0, 0.8);
125 text-shadow: 0 0 8px rgba(231, 0, 0, 0.8);
126 }
127 50% {
128 color: #e70000;
129 text-shadow: 0 0 10px #e70000;
130 }
131 }
132
133 @keyframes msgopen {
134 0% {
135 transform: scale(0, 0);
136 }
137 1% {
138 transform: scale(0, 0.01);
139 }
140 60% {
141 transform: scale(1, 0.01);
142 }
143 100% {
144 transform: scale(1, 1);
145 }
146 }
147
148 ::selection {
149 background: rgba(255, 255, 255, 0.05);
150 }
151 </style>
152</head>
153<body>
154 <div class="effects"></div>
155 <div class="overlays">
156 <div class="msgbox"><span>_</span></div>
157 <div class="loading"><span>CONNECTING</span></div>
158 <div class="error"><span>ERROR</span></div>
159 </div>
160 <canvas id="c"></canvas>
161
162 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
163 <script>
164 /* CONFIG */
165 var chars = ["0", "1"];
166 var fontsize = 20;
167 var subreddits = ["worldnews"];
168 var displayTime = 1000 * 10;
169 var typeDelay = 25;
170
171 function getRandomInt(min, max) {
172 return Math.floor(Math.random() * (max - min + 1)) + min;
173 }
174
175 (function() {
176 var lastTime = 0;
177 var vendors = ['ms', 'moz', 'webkit', 'o'];
178 for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
179 window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
180 window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
181 }
182
183 if (!window.requestAnimationFrame)
184 window.requestAnimationFrame = function(callback, element) {
185 var currTime = new Date().getTime();
186 var timeToCall = Math.max(0, 16 - (currTime - lastTime));
187 var id = window.setTimeout(function() {
188 callback(currTime + timeToCall);
189 }, timeToCall);
190 lastTime = currTime + timeToCall;
191 return id;
192 };
193
194 if (!window.cancelAnimationFrame)
195 window.cancelAnimationFrame = function(id) {
196 clearTimeout(id);
197 };
198 }());
199
200 var c, c2, cwidth, cheight, ctx, ctx2;
201 var yPositions = new Array(300).join(0).split('');
202
203 function draw() {
204 ctx.shadowColor = "rgba(0,0,0,0)";
205 ctx.fillStyle = 'rgba(0,0,0,.05)';
206 ctx.fillRect(0, 0, cwidth, cheight);
207
208 ctx.fillStyle = '#d3ffd3';
209 ctx.shadowColor = "#d3ffd3";
210
211 if ($('body').hasClass('loaded')) {
212 ctx.fillStyle = '#00e700';
213 ctx.shadowColor = "#00e700";
214 }
215
216 if ($('body').hasClass('failure')) {
217 ctx.fillStyle = '#e70000';
218 ctx.shadowColor = "#e70000";
219 }
220
221 ctx.font = '20pt Source Code Pro';
222 ctx.shadowOffsetX = 0;
223 ctx.shadowOffsetY = 0;
224 ctx.shadowBlur = 10;
225
226 yPositions.map(function(y, index) {
227 var text = chars[getRandomInt(0, chars.length - 1)];
228 var x = (index * fontsize) + fontsize;
229 c.getContext('2d').fillText(text, x, y);
230 if (y > 100 + Math.random() * 1e4) {
231 yPositions[index] = 0;
232 } else {
233 yPositions[index] = y + fontsize;
234 }
235 });
236 }
237
238 var fetchAtOnce = 100;
239 var titles = [];
240 var lastpost;
241 var errorthrown = false;
242 var fetchrunning = false;
243 var cTitle = "";
244 var lastType;
245 var lastNews = 0;
246 var msgBox;
247
248 function renderText() {
249 if (Date.now() - lastType < typeDelay) {
250 return;
251 }
252 lastType = new Date();
253 if (cTitle.length === 0) {
254 if (msgBox.html().length === 1) {
255 cTitle = titles[0];
256 if (cTitle.length === 0) {
257 errorthrown = true;
258 return;
259 }
260 titles.splice(0, 1);
261 lastNews = new Date();
262 } else {
263 if (Date.now() - lastNews > displayTime) {
264 var before = msgBox.html();
265 msgBox.html(msgBox.html().substring(0, msgBox.html().length - 2) + '_');
266 if (before === msgBox.html()) {
267 msgBox.html(msgBox.html().substring(0, msgBox.html().length - 5));
268 }
269 }
270 }
271 } else {
272 if (cTitle.length > 0) {
273 msgBox.html(msgBox.html().substr(0, msgBox.html().length - 1) + cTitle[0] + '_');
274 cTitle = cTitle.slice(1);
275 }
276 }
277 }
278
279 function getNewPosts() {
280 fetchrunning = true;
281 var req = 'https://www.reddit.com/r/' + subreddits.join('+') + '/hot/.json?limit=' + fetchAtOnce;
282 if (lastpost !== undefined && lastpost.length > 0) {
283 req += '&after=t3_' + lastpost;
284 }
285 $.getJSON(req, function(data) {
286 var children = data.data.children;
287 $.each(children, function(i, item) {
288 titles.push(item.data.title);
289 });
290 if (children && children.length > 0) {
291 lastpost = children[children.length - 1].data.id;
292 } else {
293 lastpost = undefined;
294 }
295 fetchrunning = false;
296 }).fail(function() {
297 errorthrown = true;
298 });
299 }
300
301 var fpslock = 30;
302 var lastloop = 0;
303 var isLoading = true;
304 var isActive = false;
305
306 function mainLoop() {
307 if (Date.now() - lastloop >= 1000 / fpslock) {
308 lastloop = Date.now();
309 draw();
310 if (isActive === true) {
311 if (errorthrown !== false) {
312 $('.loading, .msgbox').removeClass('flex').css('display', 'none');
313 $('.error').addClass('flex');
314 $('body').addClass('failure');
315 } else {
316 if (fetchrunning === false && titles.length < 10) {
317 getNewPosts();
318 }
319 if (isLoading === true) {
320 if (fetchrunning === false) {
321 isLoading = false;
322 $('.loading').removeClass('flex').css('display', 'none');
323 $('.msgbox').css('display', 'initial');
324 $('body').addClass('loaded');
325 }
326 } else {
327 renderText();
328 }
329 }
330 }
331 }
332 requestAnimationFrame(mainLoop);
333 }
334
335 $(document).ready(function() {
336 c = $('#c').get(0);
337 $('#c').css('height', $(window).height());
338 $('#c').css('width', $(window).width());
339 cwidth = c.width = $('body').width();
340 cheight = c.height = $('body').height();
341 ctx = c.getContext('2d');
342 c2 = document.createElement('canvas');
343 c2.width = c.width;
344 c2.height = c.height;
345 ctx2 = c2.getContext('2d');
346 msgBox = $('.msgbox span');
347
348 $('.loading').addClass('flex');
349 mainLoop();
350 setTimeout(function() {
351 isActive = true;
352 }, 3000);
353 });
354 </script>
355</body>
356</html>
HTML Breakdown
<canvas> → Renders Matrix rain animation
.msgbox → Displays typed news headlines
.loading → Connection overlay
.error → Error state UI
.effects → CRT / noise overlay
🎨 CSS – Matrix Look & UI Effects
Core Styling
1html, body, canvas { 2 font-family: monospace; 3 background: #000; 4 width: 100%; 5 height: 100%; 6 margin: 0; 7 padding: 0; 8 overflow: hidden; 9} 10 11body > div, body canvas { 12 position: absolute; 13 top: 0; 14 bottom: 0; 15 left: 0; 16 right: 0; 17} 18 19canvas { 20 z-index: 10; 21 opacity: 0.8; 22} 23 24.flex { 25 display: flex !important; 26} 27 28.effects { 29 z-index: 100; 30 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAQAAAD41K0JAAAADklEQVQI12Ng+A+EQAQADfsC/pD7Z48AAAAASUVORK5CYII=); 31 background-repeat: repeat; 32 opacity: 0.1; 33 pointer-events: none; 34} 35 36.overlays { 37 z-index: 50; 38 display: flex; 39 justify-content: center; 40 align-items: center; 41} 42.overlays .loading, .overlays .error, .overlays .msgbox { 43 width: 400px; 44 height: 140px; 45 border: 7px solid; 46 display: none; 47 justify-content: center; 48 align-items: center; 49 font-family: "Ubuntu Mono"; 50 font-weight: 600; 51 font-size: 55px; 52 letter-spacing: 5px; 53 -webkit-animation: msgopen ease-in-out 1; 54 animation: msgopen ease-in-out 1; 55 -webkit-animation-duration: 0.4s; 56 animation-duration: 0.4s; 57 -webkit-animation-fill-mode: forwards; 58 animation-fill-mode: forwards; 59} 60.overlays .loading { 61 color: #00e700; 62 border-color: rgba(0, 231, 0, 0.8); 63 background: rgba(0, 66, 0, 0.85); 64 text-shadow: 0 0 10px #00e700; 65 box-shadow: 0 0 20px rgba(0, 231, 0, 0.7); 66} 67.overlays .loading span { 68 -webkit-animation: loadingblink 1.5s linear infinite; 69 animation: loadingblink 1.5s linear infinite; 70} 71.overlays .error { 72 color: #e70000; 73 border-color: rgba(231, 0, 0, 0.8); 74 background: rgba(66, 0, 0, 0.85); 75 text-shadow: 0 0 10px #e70000; 76 box-shadow: 0 0 20px rgba(231, 0, 0, 0.7); 77} 78.overlays .error span { 79 -webkit-animation: errorblink 2s linear infinite; 80 animation: errorblink 2s linear infinite; 81} 82.overlays .msgbox { 83 color: #d3ffd3; 84 border-color: rgba(211, 255, 211, 0.8); 85 background: rgba(45, 81, 45, 0.85); 86 text-shadow: 0 0 10px rgba(211, 255, 211, 0.8); 87 box-shadow: 0 0 20px rgba(211, 255, 211, 0.5); 88 width: 500px; 89 height: auto; 90 min-height: 50px; 91 padding: 20px 25px; 92 font-weight: 400; 93 font-size: 24px; 94 line-height: 40px; 95 letter-spacing: initial; 96 overflow: hidden; 97} 98.overlays .msgbox span { 99 word-wrap: break-word; 100 position: relative; 101 /*&::before { 102 content:'> '; 103 } 104 &::after { 105 content:'_'; 106 animation:hardblink 1s linear infinite; 107 } 108 */ 109} 110 111@-webkit-keyframes loadingblink { 112 0% { 113 color: rgba(0, 231, 0, 0.6); 114 text-shadow: 0 0 6px rgba(0, 231, 0, 0.6); 115 } 116 50% { 117 color: #00e700; 118 text-shadow: 0 0 10px #00e700; 119 } 120 100% { 121 color: rgba(0, 231, 0, 0.6); 122 text-shadow: 0 0 6px rgba(0, 231, 0, 0.6); 123 } 124} 125 126@keyframes loadingblink { 127 0% { 128 color: rgba(0, 231, 0, 0.6); 129 text-shadow: 0 0 6px rgba(0, 231, 0, 0.6); 130 } 131 50% { 132 color: #00e700; 133 text-shadow: 0 0 10px #00e700; 134 } 135 100% { 136 color: rgba(0, 231, 0, 0.6); 137 text-shadow: 0 0 6px rgba(0, 231, 0, 0.6); 138 } 139} 140@-webkit-keyframes errorblink { 141 0% { 142 color: rgba(231, 0, 0, 0.8); 143 text-shadow: 0 0 8px rgba(231, 0, 0, 0.8); 144 } 145 50% { 146 color: #e70000; 147 text-shadow: 0 0 10px #e70000; 148 } 149 100% { 150 color: rgba(231, 0, 0, 0.8); 151 text-shadow: 0 0 8px rgba(231, 0, 0, 0.8); 152 } 153} 154@keyframes errorblink { 155 0% { 156 color: rgba(231, 0, 0, 0.8); 157 text-shadow: 0 0 8px rgba(231, 0, 0, 0.8); 158 } 159 50% { 160 color: #e70000; 161 text-shadow: 0 0 10px #e70000; 162 } 163 100% { 164 color: rgba(231, 0, 0, 0.8); 165 text-shadow: 0 0 8px rgba(231, 0, 0, 0.8); 166 } 167} 168@-webkit-keyframes msgopen { 169 0% { 170 transform: scale(0, 0); 171 } 172 1% { 173 transform: scale(0, 0.01); 174 } 175 60% { 176 transform: scale(1, 0.01); 177 } 178 100% { 179 transform: scale(1, 1); 180 } 181} 182@keyframes msgopen { 183 0% { 184 transform: scale(0, 0); 185 } 186 1% { 187 transform: scale(0, 0.01); 188 } 189 60% { 190 transform: scale(1, 0.01); 191 } 192 100% { 193 transform: scale(1, 1); 194 } 195} 196@-webkit-keyframes fadein { 197 0% { 198 opacity: 0; 199 } 200 100% { 201 opacity: 1; 202 } 203} 204@keyframes fadein { 205 0% { 206 opacity: 0; 207 } 208 100% { 209 opacity: 1; 210 } 211} 212@-webkit-keyframes hardblink { 213 0% { 214 opacity: 0; 215 } 216 49% { 217 opacity: 0; 218 } 219 50% { 220 opacity: 1; 221 } 222 100% { 223 opacity: 1; 224 } 225} 226@keyframes hardblink { 227 0% { 228 opacity: 0; 229 } 230 49% { 231 opacity: 0; 232 } 233 50% { 234 opacity: 1; 235 } 236 100% { 237 opacity: 1; 238 } 239} 240::-moz-selection { 241 background: rgba(255, 255, 255, 0.05); 242} 243::selection { 244 background: rgba(255, 255, 255, 0.05); 245} 246
Visual Highlights
Neon green terminal glow
CRT-style scanline overlay
Animated blinking text
Smooth open animation for message boxes
Selection highlight reduced for realism
⚙️ JavaScript – Logic & Animation
Configuration
1/* CONFIG HERE */
2var chars = ["0", "1"];
3var fontsize = 20;
4var subreddits = ["worldnews"];
5var displayTime = 1000 * 10;
6var typeDelay = 25;
7/* END OF CONFIG */
8
9function getRandomInt(min, max) {
10 return Math.floor(Math.random() * (max - min + 1)) + min;
11}
12
13(function() {
14 var lastTime = 0;
15 var vendors = ['ms', 'moz', 'webkit', 'o'];
16 for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
17 window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
18 window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
19 }
20
21 if (!window.requestAnimationFrame)
22 window.requestAnimationFrame = function(callback, element) {
23 var currTime = new Date().getTime();
24 var timeToCall = Math.max(0, 16 - (currTime - lastTime));
25 var id = window.setTimeout(function() {
26 callback(currTime + timeToCall);
27 },
28 timeToCall);
29 lastTime = currTime + timeToCall;
30 return id;
31 };
32
33 if (!window.cancelAnimationFrame)
34 window.cancelAnimationFrame = function(id) {
35 clearTimeout(id);
36 };
37}());
38
39var c, c2, cwidth, cheight, ctx, ctx2;
40var yPositions = new Array(300).join(0).split('');
41
42function draw() {
43 ctx.shadowColor = "rgba(0,0,0,0)";
44 ctx.fillStyle = 'rgba(0,0,0,.05)';
45 ctx.fillRect(0, 0, cwidth, cheight);
46
47 /*
48 ctx2.clearRect(0,0,c2.width,c2.height);
49 ctx2.drawImage(c, 0,0);
50 ctx.clearRect(0,0,c.width,c.height);
51 ctx.globalAlpha = 0.95;
52 ctx.drawImage(c2,0,0);
53 */
54
55 ctx.fillStyle = '#d3ffd3';
56 ctx.shadowColor = "#d3ffd3";
57 if ($('body').hasClass('loaded')) {
58 ctx.fillStyle = '#00e700';
59 ctx.shadowColor = "#00e700";
60 }
61
62 if ($('body').hasClass('failure')) {
63 ctx.fillStyle = '#e70000';
64 ctx.shadowColor = "#e70000";
65 }
66 ctx.font = '20pt Source Code Pro';
67 ctx.shadowOffsetX = 0;
68 ctx.shadowOffsetY = 0;
69 ctx.shadowBlur = 10;
70
71 yPositions.map(function(y, index) {
72 var text = chars[getRandomInt(0, chars.length - 1)];
73 var x = (index * fontsize) + fontsize;
74 c.getContext('2d').fillText(text, x, y);
75 if (y > 100 + Math.random() * 1e4) {
76 yPositions[index] = 0;
77 } else {
78 yPositions[index] = y + fontsize;
79 }
80 });
81
82}
83
84var fetchAtOnce = 100;
85var titles = [];
86var lastpost;
87var errorthrown = false;
88var fetchrunning = false;
89var cTitle = "";
90var lastType;
91var lastNews = 0;
92var msgBox;
93
94function renderText() {
95
96 if (Date.now() - lastType < typeDelay) {
97 return;
98 }
99 lastType = new Date();
100 if (cTitle.length === 0) { //either we're happily displaying or currently removing old news
101 if (msgBox.html().length === 1) { //let's insert a new text!
102 cTitle = titles[0];
103 if (cTitle.length === 0) {
104 errorthrown = true;
105 return;
106 }
107 titles.splice(0, 1);
108 lastNews = new Date();
109 } else { //remove old text
110 if (Date.now() - lastNews > displayTime) {
111 var before = msgBox.html();
112 msgBox.html(msgBox.html().substring(0, msgBox.html().length - 2) + '_');
113 if (before === msgBox.html()) {
114 msgBox.html(msgBox.html().substring(0, msgBox.html().length - 5));
115 }
116 }
117 }
118 } else { //seems we need to wait OR add to the title
119 if (cTitle.length > 0) {
120 msgBox.html(msgBox.html().substr(0, msgBox.html().length - 1) + cTitle[0] + '_');
121 cTitle = cTitle.slice(1);
122 }
123 }
124}
125
126function getNewPosts() {
127 fetchrunning = true;
128 var req = 'https://www.reddit.com/r/' + subreddits.join('+') + '/hot/.json?limit=' + fetchAtOnce;
129 if (lastpost !== undefined && lastpost.length > 0) {
130 req += '&after=t3_' + lastpost;
131 }
132 $.getJSON(req, function(data) {
133 var children = data.data.children;
134 $.each(children, function(i, item) {
135 titles.push(item.data.title);
136 });
137 if (children && children.length > 0) {
138 lastpost = children[children.length - 1].data.id;
139 } else {
140 lastpost = undefined;
141 }
142 fetchrunning = false;
143 }).fail(function() {
144 errorthrown = true;
145 });
146}
147
148var fpslock = 30;
149var lastloop = 0;
150var isLoading = true;
151var isActive = false;
152
153function mainLoop() {
154 if (Date.now() - lastloop >= 1000 / fpslock) {
155 lastloop = Date.now();
156 draw();
157 if (isActive === true) {
158 if (errorthrown !== false) {
159 $('.loading, .msgbox').removeClass('flex').css('display', 'none');
160 $('.error').addClass('flex');
161 $('body').addClass('failure');
162 } else {
163 if (fetchrunning === false && titles.length < 10) {
164 getNewPosts();
165 }
166 if (isLoading === true) {
167 if (fetchrunning === false) {
168 isLoading = false;
169 $('.loading').removeClass('flex').css('display', 'none');
170 $('.msgbox').css('display', 'initial');
171 $('body').addClass('loaded');
172 }
173 } else {
174 renderText();
175 }
176 }
177 }
178 }
179
180 requestAnimationFrame(mainLoop);
181}
182
183$(document).ready(function() {
184 c = $('#c').get(0);
185 $('#c').css('height', $(window).height());
186 $('#c').css('width', $(window).width());
187 cwidth = c.width = $('body').width();
188 cheight = c.height = $('body').height();
189 ctx = c.getContext('2d');
190 c2 = document.createElement('canvas');
191 c2.width = c.width;
192 c2.height = c.height;
193 ctx2 = c2.getContext('2d');
194 msgBox = $('.msgbox span');
195
196 $('.loading').addClass('flex');
197 mainLoop();
198 setTimeout(function() {
199 isActive = true;
200 }, 3000);
201});
202