PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
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 / interactive-gradient-mesh / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.11, at blocks/interactive-gradient-mesh/frontend.js

204 lines 8.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 'use strict';
3
4 var typoMap = [
5 ['family','font-family'],['weight','font-weight'],['style','font-style'],
6 ['decoration','text-decoration'],['transform','text-transform'],
7 ['sizeDesktop','font-size-d'],['sizeTablet','font-size-t'],['sizeMobile','font-size-m'],
8 ['lineHeightDesktop','line-height-d'],['lineHeightTablet','line-height-t'],['lineHeightMobile','line-height-m'],
9 ['letterSpacingDesktop','letter-spacing-d'],['letterSpacingTablet','letter-spacing-t'],['letterSpacingMobile','letter-spacing-m'],
10 ['wordSpacingDesktop','word-spacing-d'],['wordSpacingTablet','word-spacing-t'],['wordSpacingMobile','word-spacing-m']
11 ];
12 function typoCssVarsForEl(typo, prefix, el) {
13 if (!typo || typeof typo !== 'object') return;
14 for (var i = 0; i < typoMap.length; i++) {
15 var v = typo[typoMap[i][0]];
16 if (v !== undefined && v !== '' && v !== null) el.style.setProperty(prefix + typoMap[i][1], String(v));
17 }
18 }
19
20 function lerp(a, b, t) { return a + (b - a) * t; }
21
22 function hexToRgb(hex) {
23 hex = hex.replace('#', '');
24 if (hex.length === 3) hex = hex.split('').map(function (c) { return c + c; }).join('');
25 var n = parseInt(hex, 16);
26 return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
27 }
28
29 document.querySelectorAll('.bkbg-igm-app').forEach(function (app) {
30 var o;
31 try { o = JSON.parse(app.dataset.opts || '{}'); } catch (e) { return; }
32
33 var colors = Array.isArray(o.colors) && o.colors.length ? o.colors : ['#6366f1','#f43f5e','#06b6d4','#f59e0b'];
34 var blobCount = Math.min(o.blobCount || 5, colors.length);
35 var blobSize = o.blobSize || 55;
36 var blurAmount = o.blurAmount || 80;
37 var blendMode = o.blendMode || 'screen';
38 var mouseInfluence = o.mouseInfluence || 30;
39 var autoAnimate = !!o.autoAnimate;
40 var animSpeed = o.animateSpeed || 0.6;
41 var baseBg = o.baseBg || '#0f172a';
42 var height = o.height || 480;
43 var showContent = !!o.showContent;
44 var heading = o.heading || '';
45 var subheading = o.subheading || '';
46 var ctaText = o.ctaText || '';
47 var ctaUrl = o.ctaUrl || '#';
48 var headingSize = o.headingSize || 48;
49 var subheadingSize = o.subheadingSize || 18;
50 var headingColor = o.headingColor || '#ffffff';
51 var subheadingColor= o.subheadingColor || 'rgba(255,255,255,0.75)';
52 var ctaBg = o.ctaBg || '#ffffff';
53 var ctaColor = o.ctaColor || '#0f172a';
54 var ctaRadius = o.ctaRadius || 100;
55 var contentAlign = o.contentAlign || 'center';
56
57 var reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
58
59 /* ── App container ── */
60 app.style.height = height + 'px';
61 app.style.background = baseBg;
62 app.classList.add('bkbg-igm-align-' + contentAlign);
63 typoCssVarsForEl(o.headingTypo, '--bkbg-igm-h-', app);
64 typoCssVarsForEl(o.subheadingTypo, '--bkbg-igm-sh-', app);
65
66 /* ── Canvas ── */
67 var canvas = document.createElement('canvas');
68 canvas.className = 'bkbg-igm-canvas';
69 app.appendChild(canvas);
70
71 var ctx = canvas.getContext('2d');
72
73 function resize() {
74 canvas.width = app.offsetWidth;
75 canvas.height = app.offsetHeight;
76 }
77 resize();
78 window.addEventListener('resize', function () { resize(); });
79
80 /* ── Blobs ── */
81 var blobs = [];
82 for (var i = 0; i < blobCount; i++) {
83 var color = colors[i % colors.length];
84 var rgb = hexToRgb(color);
85 blobs.push({
86 x: Math.random(),
87 y: Math.random(),
88 tx: Math.random(),
89 ty: Math.random(),
90 r: rgb,
91 phase: Math.random() * Math.PI * 2,
92 spd: 0.2 + Math.random() * 0.6
93 });
94 }
95
96 /* ── Mouse tracking ── */
97 var mouseX = 0.5, mouseY = 0.5;
98 app.addEventListener('mousemove', function (e) {
99 var rect = app.getBoundingClientRect();
100 mouseX = (e.clientX - rect.left) / rect.width;
101 mouseY = (e.clientY - rect.top) / rect.height;
102 });
103
104 /* ── Render loop ── */
105 var lastTime = null;
106 var rafId = null;
107 var elapsed = 0;
108
109 function draw(ts) {
110 if (!lastTime) lastTime = ts;
111 var dt = (ts - lastTime) / 1000;
112 lastTime = ts;
113 elapsed += dt * animSpeed;
114
115 var W = canvas.width;
116 var H = canvas.height;
117
118 ctx.clearRect(0, 0, W, H);
119
120 blobs.forEach(function (blob, i) {
121 /* auto movement */
122 if (autoAnimate && !reducedMotion) {
123 blob.x = 0.5 + 0.4 * Math.sin(elapsed * blob.spd + blob.phase);
124 blob.y = 0.5 + 0.4 * Math.cos(elapsed * blob.spd * 0.7 + blob.phase + 1);
125 }
126
127 /* mouse influence */
128 var px = blob.x + (mouseX - 0.5) * (mouseInfluence / 100);
129 var py = blob.y + (mouseY - 0.5) * (mouseInfluence / 100);
130
131 var bx = W * Math.max(0, Math.min(1, px));
132 var by = H * Math.max(0, Math.min(1, py));
133 var br = Math.min(W, H) * (blobSize / 100);
134
135 var grad = ctx.createRadialGradient(bx, by, 0, bx, by, br);
136 grad.addColorStop(0, 'rgba(' + blob.r[0] + ',' + blob.r[1] + ',' + blob.r[2] + ',0.85)');
137 grad.addColorStop(1, 'rgba(' + blob.r[0] + ',' + blob.r[1] + ',' + blob.r[2] + ',0)');
138
139 ctx.save();
140 ctx.filter = 'blur(' + blurAmount + 'px)';
141 ctx.globalCompositeOperation = blendMode;
142 ctx.fillStyle = grad;
143 ctx.beginPath();
144 ctx.arc(bx, by, br, 0, Math.PI * 2);
145 ctx.fill();
146 ctx.restore();
147 });
148
149 rafId = requestAnimationFrame(draw);
150 }
151
152 /* ── Intersection observer ── */
153 var observer = new IntersectionObserver(function (entries) {
154 entries.forEach(function (entry) {
155 if (entry.isIntersecting) {
156 lastTime = null;
157 rafId = requestAnimationFrame(draw);
158 } else {
159 if (rafId) { cancelAnimationFrame(rafId); rafId = null; }
160 }
161 });
162 }, { threshold: 0.05 });
163 observer.observe(app);
164
165 /* ── Content ── */
166 if (showContent) {
167 var content = document.createElement('div');
168 content.className = 'bkbg-igm-content';
169
170 var inner = document.createElement('div');
171 inner.className = 'bkbg-igm-inner';
172
173 if (heading) {
174 var h2 = document.createElement('h2');
175 h2.className = 'bkbg-igm-heading';
176 h2.style.color = headingColor;
177 h2.textContent = heading;
178 inner.appendChild(h2);
179 }
180 if (subheading) {
181 var p = document.createElement('p');
182 p.className = 'bkbg-igm-subheading';
183 p.style.color = subheadingColor;
184 p.textContent = subheading;
185 inner.appendChild(p);
186 }
187 if (ctaText) {
188 var a = document.createElement('a');
189 a.className = 'bkbg-igm-cta';
190 a.href = ctaUrl;
191 a.style.background = ctaBg;
192 a.style.color = ctaColor;
193 a.style.borderRadius = ctaRadius + 'px';
194 a.style.fontSize = '15px';
195 a.textContent = ctaText;
196 inner.appendChild(a);
197 }
198
199 content.appendChild(inner);
200 app.appendChild(content);
201 }
202 });
203 }());
204