PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / matrix-rain / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/matrix-rain/frontend.js

219 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 var _typoKeys = { family:'font-family', weight:'font-weight', style:'font-style',
2 decoration:'text-decoration', transform:'text-transform',
3 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
4 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
5 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
6 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m' };
7 function typoCssVarsForEl(el, typo, prefix) {
8 if (!typo || typeof typo !== 'object') return;
9 Object.keys(_typoKeys).forEach(function (k) {
10 if (typo[k] !== undefined && typo[k] !== '') el.style.setProperty(prefix + _typoKeys[k], String(typo[k]));
11 });
12 }
13
14 document.addEventListener('DOMContentLoaded', function () {
15 document.querySelectorAll('.bkbg-mr-app').forEach(function (root) {
16 var opts = JSON.parse(root.dataset.opts || '{}');
17 initMatrixRain(root, opts);
18 });
19 });
20
21 /* character set helpers */
22 var KATA = 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン';
23 function getChars(a) {
24 if (a.charSet === 'binary') return ['0','1'];
25 if (a.charSet === 'hex') return '0123456789ABCDEF'.split('');
26 if (a.charSet === 'latin') return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('');
27 if (a.charSet === 'custom') return ((a.customChars || '01').split(''));
28 return (KATA + '0123456789').split('');
29 }
30
31 function hslColumn(colIdx, total) {
32 return 'hsl(' + Math.round((colIdx / total) * 360) + ',100%,55%)';
33 }
34
35 function initMatrixRain(root, a) {
36 var height = a.height || 400;
37 var fontSize = a.fontSize || 16;
38 var speed = a.speed || 50;
39 var bgOp = (a.bgOpacity || 8) / 100;
40 var density = (a.density || 100) / 100;
41 var primary = a.primaryColor || '#00ff41';
42 var headCol = a.headColor || '#ffffff';
43 var bgColor = a.bgColor || '#000000';
44 var chars = getChars(a);
45 var isRainbow = (a.colorStyle === 'rainbow');
46 var glowOn = a.glowEffect !== false;
47
48 /* build DOM */
49 var wrap = document.createElement('div');
50 wrap.className = 'bkbg-mr-wrap';
51 wrap.style.height = height + 'px';
52
53 typoCssVarsForEl(wrap, a.overlayTypo, '--bkbg-mr-ot-');
54 typoCssVarsForEl(wrap, a.subtextTypo, '--bkbg-mr-os-');
55
56 var canvas = document.createElement('canvas');
57 canvas.className = 'bkbg-mr-canvas';
58 canvas.height = height;
59 wrap.appendChild(canvas);
60
61 /* overlay text */
62 if (a.showOverlay) {
63 var overlay = document.createElement('div');
64 overlay.className = 'bkbg-mr-overlay';
65 overlay.style.background = a.overlayBg || 'rgba(0,0,0,0.35)';
66
67 if (a.overlayText) {
68 var ot = document.createElement('h2');
69 ot.className = 'bkbg-mr-overlay-title';
70 ot.style.color = a.overlayTextColor || '#00ff41';
71 ot.textContent = a.overlayText;
72 overlay.appendChild(ot);
73 }
74 if (a.overlaySubtext) {
75 var os = document.createElement('p');
76 os.className = 'bkbg-mr-overlay-sub';
77 os.style.color = a.overlayTextColor || '#00ff41';
78 os.textContent = a.overlaySubtext;
79 overlay.appendChild(os);
80 }
81 wrap.appendChild(overlay);
82 }
83
84 root.appendChild(wrap);
85
86 /* canvas sizing */
87 var ctx = canvas.getContext('2d');
88 function resize() {
89 canvas.width = wrap.offsetWidth || window.innerWidth;
90 canvas.height = height;
91 initDrops();
92 }
93
94 var drops = [];
95 function initDrops() {
96 var cols = Math.floor(canvas.width / fontSize);
97 drops = [];
98 for (var i = 0; i < cols; i++) {
99 if (Math.random() > density) {
100 drops.push(null); /* skip column based on density */
101 } else {
102 drops.push(a.randomStart ? Math.floor(Math.random() * -(height / fontSize)) : 0);
103 }
104 }
105 }
106
107 resize();
108 window.addEventListener('resize', resize);
109
110 /* animation */
111 var paused = false;
112 var raf = null;
113 var lastTime = 0;
114 var interval = 1000 / (speed / 10 + 5);
115 var pauseBadge = null;
116
117 function draw(ts) {
118 raf = requestAnimationFrame(draw);
119 if (paused) return;
120 if (ts - lastTime < interval) return;
121 lastTime = ts;
122
123 /* fade trail */
124 ctx.fillStyle = hexToRgba(bgColor, bgOp);
125 ctx.fillRect(0, 0, canvas.width, canvas.height);
126
127 if (glowOn) {
128 ctx.shadowBlur = 8;
129 ctx.shadowColor = primary;
130 } else {
131 ctx.shadowBlur = 0;
132 }
133
134 ctx.font = fontSize + 'px monospace';
135
136 var cols = drops.length;
137 for (var i = 0; i < cols; i++) {
138 if (drops[i] === null) continue;
139
140 var ch = chars[Math.floor(Math.random() * chars.length)];
141 var x = i * fontSize;
142 var y = drops[i] * fontSize;
143
144 /* head char (bright white / highlight) */
145 ctx.fillStyle = headCol;
146 ctx.fillText(ch, x, y);
147
148 /* fade the previous cells to primary color */
149 if (isRainbow) {
150 ctx.fillStyle = hslColumn(i, cols);
151 } else {
152 ctx.fillStyle = primary;
153 }
154
155 /* draw a few chars above the head position in faded color to extend trail */
156 var trailLen = Math.min(a.fadeLength || 20, Math.floor(Math.random() * 8) + 4);
157 for (var t = 1; t <= trailLen; t++) {
158 var ty = (drops[i] - t) * fontSize;
159 if (ty < 0) break;
160 var alpha = 1 - t / trailLen;
161 if (isRainbow) {
162 ctx.fillStyle = 'hsla(' + Math.round((i / cols) * 360) + ',100%,55%,' + alpha + ')';
163 } else {
164 ctx.fillStyle = hexToRgbaFull(primary, alpha);
165 }
166 ctx.fillText(chars[Math.floor(Math.random() * chars.length)], x, ty);
167 }
168
169 if (y > canvas.height && Math.random() > 0.975) {
170 drops[i] = 0;
171 }
172 drops[i]++;
173 }
174 }
175
176 raf = requestAnimationFrame(draw);
177
178 /* pause/resume badge */
179 function togglePause() {
180 paused = !paused;
181 if (paused) {
182 if (!pauseBadge) {
183 pauseBadge = document.createElement('div');
184 pauseBadge.className = 'bkbg-mr-paused-badge';
185 pauseBadge.textContent = '■ PAUSED';
186 wrap.appendChild(pauseBadge);
187 }
188 pauseBadge.style.display = 'block';
189 } else {
190 if (pauseBadge) pauseBadge.style.display = 'none';
191 }
192 }
193
194 if (a.clickToPause) {
195 canvas.addEventListener('click', togglePause);
196 if (a.showOverlay && overlay) overlay.style.pointerEvents = 'auto';
197 }
198 if (a.pauseOnHover) {
199 canvas.addEventListener('mouseenter', function () { if (!paused) { paused = true; } });
200 canvas.addEventListener('mouseleave', function () { paused = false; });
201 }
202
203 /* cleanup on page unload */
204 window.addEventListener('beforeunload', function () { cancelAnimationFrame(raf); });
205 }
206
207 function hexToRgba(hex, alpha) {
208 var r = 0, g = 0, b = 0;
209 if (hex && hex.startsWith('#')) {
210 var h = hex.replace('#','');
211 if (h.length === 3) h = h[0]+h[0]+h[1]+h[1]+h[2]+h[2];
212 r = parseInt(h.slice(0,2),16) || 0;
213 g = parseInt(h.slice(2,4),16) || 0;
214 b = parseInt(h.slice(4,6),16) || 0;
215 }
216 return 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')';
217 }
218 function hexToRgbaFull(hex, alpha) { return hexToRgba(hex, alpha); }
219