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 / glitch-text / frontend.js

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

146 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* Glitch Text — frontend */
2 (function () {
3 'use strict';
4
5 /* ── utilities ──────────────────────────────────────────────────────────── */
6 function rand(min, max) {
7 return Math.random() * (max - min) + min;
8 }
9
10 function randInt(min, max) {
11 return Math.floor(rand(min, max));
12 }
13
14 /* ── chromatic effect: inject clone elements ─────────────────────────────── */
15 function injectClones(outer, textEl) {
16 if (outer._bkglClones) { return; }
17 outer._bkglClones = true;
18
19 var redClone = textEl.cloneNode(true);
20 var blueClone = textEl.cloneNode(true);
21
22 redClone.className = (redClone.className || '') + ' bkgl-clone bkgl-clone-red';
23 blueClone.className = (blueClone.className || '') + ' bkgl-clone bkgl-clone-blue';
24 redClone.setAttribute('aria-hidden', 'true');
25 blueClone.setAttribute('aria-hidden', 'true');
26 redClone.style.position = 'absolute';
27 blueClone.style.position = 'absolute';
28 redClone.style.top = '0';
29 blueClone.style.top = '0';
30 redClone.style.width = '100%';
31 blueClone.style.width = '100%';
32
33 outer.appendChild(redClone);
34 outer.appendChild(blueClone);
35 }
36
37 /* ── noise/scramble effect ─────────────────────────────────────────────── */
38 function scramble(outer, textEl, charset, intensity, ms) {
39 if (outer._bkglScrambling) { return; }
40 outer._bkglScrambling = true;
41
42 var original = textEl.textContent || '';
43 var chars = charset.split('');
44 var steps = Math.max(4, Math.floor(ms / 60));
45 var stepMs = ms / steps;
46 var frame = 0;
47
48 function tick() {
49 if (frame >= steps) {
50 textEl.textContent = original;
51 outer._bkglScrambling = false;
52 return;
53 }
54 var progress = frame / steps;
55 var result = original.split('').map(function (ch, i) {
56 if (ch === ' ') { return ch; }
57 /* reveal characters left to right as animation progresses */
58 if (i < Math.floor(original.length * progress)) { return ch; }
59 return chars[randInt(0, chars.length)];
60 }).join('');
61 textEl.textContent = result;
62 frame++;
63 setTimeout(tick, stepMs);
64 }
65
66 tick();
67 }
68
69 /* ── play a glitch burst ────────────────────────────────────────────────── */
70 function playBurst(outer, ms) {
71 outer.classList.add('bkgl-playing');
72 setTimeout(function () {
73 outer.classList.remove('bkgl-playing');
74 }, ms);
75 }
76
77 /* ── init one block ─────────────────────────────────────────────────────── */
78 function initBlock(outer) {
79 if (outer._bkglInit) { return; }
80 outer._bkglInit = true;
81
82 var textEl = outer.querySelector('.bkgl-text');
83 if (!textEl) { return; }
84
85 var type = outer.getAttribute('data-type') || 'chromatic';
86 var trigger = outer.getAttribute('data-trigger') || 'always';
87 var ms = parseInt(outer.getAttribute('data-ms'), 10) || 800;
88 var intensity = parseInt(outer.getAttribute('data-intensity'), 10) || 6;
89 var intervalMs = parseInt(outer.getAttribute('data-interval'), 10) || 4000;
90 var burstMs = parseInt(outer.getAttribute('data-burst'), 10) || 600;
91 var charset = outer.getAttribute('data-charset') || '!<>-_\\/[]{}—=+*^?#';
92 var colorRed = outer.getAttribute('data-color-red') || outer.style.getPropertyValue('--bkgl-red') || '#ff0040';
93 var colorBlue = outer.getAttribute('data-color-blue') || outer.style.getPropertyValue('--bkgl-blue') || '#00e5ff';
94
95 /* make sure CSS vars are set on the outer element */
96 outer.style.setProperty('--bkgl-red', colorRed);
97 outer.style.setProperty('--bkgl-blue', colorBlue);
98 outer.style.setProperty('--bkgl-ms', ms + 'ms');
99 outer.style.setProperty('--bkgl-shift', intensity + 'px');
100
101 /* inject clones for chromatic & digital */
102 if (type === 'chromatic' || type === 'digital') {
103 injectClones(outer, textEl);
104 }
105
106 /* trigger logic */
107 if (trigger === 'hover') {
108 /* CSS handles play-state via :hover — nothing extra needed for chromatic */
109 if (type === 'noise' || type === 'digital') {
110 outer.addEventListener('mouseenter', function () {
111 scramble(outer, textEl, charset, intensity, ms);
112 });
113 }
114
115 } else if (trigger === 'click') {
116 outer.style.cursor = 'pointer';
117 outer.addEventListener('click', function () {
118 if (type === 'noise' || type === 'digital') {
119 scramble(outer, textEl, charset, intensity, ms);
120 }
121 playBurst(outer, burstMs);
122 });
123
124 } else if (trigger === 'interval') {
125 setInterval(function () {
126 if (type === 'noise' || type === 'digital') {
127 scramble(outer, textEl, charset, intensity, burstMs);
128 }
129 playBurst(outer, burstMs);
130 }, intervalMs);
131
132 }
133 /* trigger === 'always' → CSS handles it automatically */
134 }
135
136 function init() {
137 document.querySelectorAll('.bkgl-outer[data-type]').forEach(initBlock);
138 }
139
140 if (document.readyState === 'loading') {
141 document.addEventListener('DOMContentLoaded', init);
142 } else {
143 init();
144 }
145 }());
146