1window.addEventListener('DOMContentLoaded', () => { 2 class animatedBackground extends elementorModules.frontend.handlers.Base { 3 onInit(...args) { 4 super.onInit(...args); 5 if (this.getElementSettings('section_fluid_on') !== 'yes') { 6 return; 7 } 8 9 // the beauty can be found in details :P 10 this.hasMouseStarted = false; 11 this.mouse = { 12 x: 0.5, 13 y: 0.5, 14 vx: 0, 15 vy: 0 16 }; 17 this.targetMouse = { 18 x: 0.5, 19 y: 0.5 20 }; 21 this.damping = 0.72; 22 this.stiffness = 0.12; 23 this.canvas = null; 24 this.updateMousePosition = this.updateMousePosition.bind(this); 25 this.initBackground(); 26 } 27 28 /** 29 * Global resize handler for the fluid animation 30 */ 31 resize() { 32 const el = this.$element[0]; 33 const { 34 renderer, 35 program 36 } = el.animatedBackground; 37 renderer.setSize(el.offsetWidth, el.offsetHeight); 38 program.uniforms.uResolution.value = [el.offsetWidth, el.offsetHeight, el.offsetWidth / el.offsetHeight]; 39 } 40 41 /** 42 * Global mouse position for the fluid animation 43 * @param {*} e 44 */ 45 updateMousePosition(e) { 46 const rect = this.$element[0].getBoundingClientRect(); 47 const x = (e.clientX - rect.left) / rect.width; 48 const y = (e.clientY - rect.top) / rect.height; 49 50 //fix initial jump 51 if (!this.hasMouseStarted) { 52 this.mouse.x = x; 53 this.mouse.y = y; 54 this.targetMouse.x = x; 55 this.targetMouse.y = y; 56 this.hasMouseStarted = true; 57 return; 58 } 59 this.targetMouse.x = x; 60 this.targetMouse.y = y; 61 } 62 63 /** 64 * Global animation loop 65 * @param {*} t 66 */ 67 loop(t) { 68 const el = this.$element[0]; 69 const { 70 renderer, 71 program, 72 mesh 73 } = el.animatedBackground; 74 this.$element[0].animationId = requestAnimationFrame(this.loop.bind(this)); 75 program.uniforms.uTime.value = t * 0.001; 76 const dx = this.targetMouse.x - this.mouse.x; 77 const dy = this.targetMouse.y - this.mouse.y; 78 79 // acceleration toward target 80 this.mouse.vx += dx * this.stiffness; 81 this.mouse.vy += dy * this.stiffness; 82 83 // apply damping (friction) 84 this.mouse.vx *= this.damping; 85 this.mouse.vy *= this.damping; 86 87 // update position 88 this.mouse.x += this.mouse.vx; 89 this.mouse.y += this.mouse.vy; 90 program.uniforms.uMouse.value = [this.mouse.x, this.mouse.y]; 91 renderer.render({ 92 scene: mesh 93 }); 94 } 95 96 /** 97 * Global destroy method 98 */ 99 destroy() { 100 const { 101 gl, 102 program, 103 geometry, 104 mesh 105 } = this.$element[0].animatedBackground; 106 107 //stop animation loop 108 if (this.$element[0].animationId) { 109 cancelAnimationFrame(this.$element[0].animationId); 110 } 111 //remove event listeners 112 this.$element[0].removeEventListener('mousemove', this.updateMousePosition); 113 window.removeEventListener('resize', this.resize); 114 115 //clean up ogl resources 116 try { 117 var _mesh$delete; 118 mesh === null || mesh === void 0 || (_mesh$delete = mesh.delete) === null || _mesh$delete === void 0 || _mesh$delete.call(mesh); 119 } catch (e) {} 120 try { 121 gl.deleteProgram(program === null || program === void 0 ? void 0 : program.program); 122 } catch (e) {} 123 try { 124 var _geometry$attributes; 125 gl.deleteBuffer(geometry === null || geometry === void 0 || (_geometry$attributes = geometry.attributes) === null || _geometry$attributes === void 0 || (_geometry$attributes = _geometry$attributes.position) === null || _geometry$attributes === void 0 ? void 0 : _geometry$attributes.buffer); 126 } catch (e) {} 127 try { 128 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 129 } catch (e) {} 130 131 //cleanup references 132 this.$element[0].animatedBackground = null; 133 } 134 135 /** 136 * Initialize the fluid animation 137 */
138 initBackground() { 139 var _this$$element$0$anim; 140 const animation = this.getElementSettings('uicore_fluid_animation') || null; 141 if (!animation) { 142 return; 143 } 144 145 // Get proper function name 146 const name = animation.replace('ui-fluid-', '').replace(/-([a-z])/g, g => g[1].toUpperCase()); 147 const functionName = 'uiAnimated_' + name.charAt(0).toUpperCase() + name.slice(1); 148 this.createCanvas(animation); 149 150 // Css based animations only need canvas 151 if (typeof window[functionName] !== 'function') { 152 return; 153 } 154 155 // Try to destroy existing animation 156 if (this.$element[0].animatedBackground) { 157 this.destroy(); 158 } 159 const settings = this.getBGSettings(); 160 window[functionName](this.$element[0], this.canvas, settings); // Calls for the main animation function 161 162 // Start loop and resize listeners if not custom 163 if ((_this$$element$0$anim = this.$element[0].animatedBackground) !== null && _this$$element$0$anim !== void 0 && _this$$element$0$anim.custom) { 164 return; 165 } 166 requestAnimationFrame(this.loop.bind(this)); 167 window.addEventListener("resize", this.resize.bind(this)); 168 this.resize(); 169 if (settings.mouseInteractive) { 170 this.$element[0].addEventListener('mousemove', this.updateMousePosition); 171 } 172 } 173 174 /** 175 * Create a canvas element for the fluid animation 176 * @param {string} animation 177 */ 178 createCanvas(animation) { 179 let canvas = this.$element[0].querySelector('.ui-e-fluid-canvas'); 180 181 //cleanup existing canvas 182 if (canvas) { 183 this.$element[0].removeChild(canvas); 184 canvas = null; 185 } 186 187 // Check if we actually need the `canvas` tag 188 const useDiv = animation.startsWith('ui-fluid-animation-') && animation !== 'ui-fluid-animation-6'; 189 canvas = useDiv ? document.createElement('div') : document.createElement('canvas'); 190 canvas.className = useDiv ? 'ui-fluid-gradient-wrapper ui-e-fluid-canvas' : 'ui-e-fluid-canvas'; 191 this.$element[0].insertBefore(canvas, this.$element[0].firstChild); 192 if (useDiv) { 193 const canvasChild = document.createElement('div'); 194 canvasChild.className = 'ui-fluid-gradient'; 195 canvas.appendChild(canvasChild); 196 } else { 197 canvas.style.position = 'absolute'; 198 canvas.style.inset = '0'; 199 canvas.style.width = '100%'; 200 canvas.style.height = '100%'; 201 canvas.style.display = 'block'; 202 } 203 this.canvas = canvas; 204 } 205 getBGColorSettings() { 206 const canvasStyle = getComputedStyle(this.canvas); 207 const colorArray = [canvasStyle.getPropertyValue("--ui-fluid-1") || "#b96d04", canvasStyle.getPropertyValue("--ui-fluid-2") || "#dd7301", canvasStyle.getPropertyValue("--ui-fluid-3") || "#f7c632", canvasStyle.getPropertyValue("--ui-fluid-4") || "#934b14"].map(color => this.getResolvedRGB(color)); 208 const backgroundColor = this.getResolvedRGB(canvasStyle.getPropertyValue("--ui-fluid-bg") || "#000000"); 209 return { 210 colorArray, 211 backgroundColor 212 }; 213 } 214 getBGSettings() { 215 var _this$getElementSetti, _this$getElementSetti2, _this$getElementSetti3, _this$getElementSetti4, _this$getElementSetti5, _this$getElementSetti6, _this$getElementSetti7, _this$getElementSetti8; 216 // If settings popover is reset or not set yet, use default values 217 let settings = this.getElementSettings('section_fluid_settings') !== 'yes' ? { 218 ...this.getBGColorSettings(), 219 scale: 10, 220 intensity: 50, 221 speed: 20, 222 noise: 20, 223 angle: 0, 224 mouseInteractive: false, 225 progress: 10 226 } : { 227 ...this.getBGColorSettings(), 228 scale: (_this$getElementSetti = this.getElementSettings('section_fluid_scale')) !== null && _this$getElementSetti !== void 0 ? _this$getElementSetti : 10, 229 intensity: (_this$getElementSetti2 = this.getElementSettings('section_fluid_intensity')) !== null && _this$getElementSetti2 !== void 0 ? _this$getElementSetti2 : 50, 230 speed: this.getElementSettings('section_fluid_static') === 'yes' ? 0 : (_this$getElementSetti3 = this.getElementSettings('section_fluid_speed')) !== null && _this$getElementSetti3 !== void 0 ? _this$getElementSetti3 : 20, 231 noise: (_this$getElementSetti4 = this.getElementSettings('section_fluid_noise')) !== null && _this$getElementSetti4 !== void 0 ? _this$getElementSetti4 : 20, 232 angle: (_this$getElementSetti5 = this.getElementSettings('section_fluid_angle')) !== null && _this$getElementSetti5 !== void 0 ? _this$getElementSetti5 : 0, 233 mouseInteractive: this.getElementSettings('section_fluid_interactive') === 'yes', 234 progress: (_this$getElementSetti6 = this.getElementSettings('section_fluid_progress')) !== null && _this$getElementSetti6 !== void 0 ? _this$getElementSetti6 : 10, 235 texture: this.getElementSettings('section_fluid_texture') || null, 236 offsetX: (_this$getElementSetti7 = this.getElementSettings('section_fluid_offset_x')) !== null && _this$getElementSetti7 !== void 0 ? _this$getElementSetti7 : 0, 237 offsetY: (_this$getElementSetti8 = this.getElementSettings('section_fluid_offset_y')) !== null && _this$getElementSetti8 !== void 0 ? _this$getElementSetti8 : 0 238 }; 239 240 // Fluid image should always be interactive 241 if (this.getElementSettings('uicore_fluid_animation') === 'liquid-image') { 242 settings.mouseInteractive = true; 243 } 244 return settings; 245 } 246 getResolvedRGB(color) { 247 const temp = document.createElement("div"); 248 temp.style.color = color; 249 window.document.body.appendChild(temp); 250 const computed = getComputedStyle(temp).color; 251 window.document.body.removeChild(temp); 252 const [r, g, b] = computed.match(/\d+/g).map(Number); 253 return [r / 255, g / 255, b / 255]; 254 } 255 updateSettings(propertyName) { 256 const map = { 257 'section_fluid_scale': { 258 key: 'scale', 259 default: 10 260 }, 261 'section_fluid_intensity': { 262 key: 'intensity', 263 default: 50 264 }, 265 'section_fluid_speed': { 266 key: 'speed', 267 default: 20 268 }, 269 'section_fluid_noise': { 270 key: 'noise', 271 default: 0 272 }, 273 'section_fluid_angle': { 274 key: 'angle', 275 default: 0 276 }, 277 'section_fluid_interactive': { 278 key: 'mouseInteractive', 279 default: false 280 }, 281 'section_fluid_static': { 282 key: 'static', 283 default: false 284 }, 285 'section_fluid_progress': { 286 key: 'progress', 287 default: 10 288 }, 289 'section_fluid_offset_x': { 290 key: 'offsetX', 291 default: 0 292 }, 293 'section_fluid_offset_y': { 294 key: 'offsetY', 295 default: 0 296 } 297 }; 298 let normalized; 299 const { 300 normalizeSettings, 301 program, 302 customUpdateSettings 303 }
303 = this.$element[0].animatedBackground; 304 if (map[propertyName]) { 305 const { 306 key, 307 default: defaultValue 308 } = map[propertyName]; 309 let value = this.getElementSettings(propertyName); 310 311 // Object props check 312 if (typeof value === 'object' && value !== null) { 313 value = value.size === null || value.size === undefined || isNaN(value.size) ? defaultValue : value.size; 314 // Switch props check 315 } else if (key === 'mouseInteractive' || key === 'static') { 316 value = value.toLowerCase() === 'yes'; 317 // Straight props check 318 } else if (value === '' || value === null || value === undefined || isNaN(value)) { 319 value = defaultValue; 320 } 321 normalized = normalizeSettings({ 322 [key]: value 323 }); 324 } 325 326 // Update colors (get them from css since those are not frontend settings) 327 if (propertyName.startsWith('section_fluid_color')) { 328 const { 329 colorArray, 330 backgroundColor 331 } = this.getBGColorSettings(); 332 normalized = normalizeSettings({ 333 colorArray, 334 backgroundColor 335 }); 336 } 337 if (normalized) { 338 if (typeof customUpdateSettings === 'function') { 339 customUpdateSettings(normalized); 340 return; 341 } 342 for (const [k, v] of Object.entries(normalized)) { 343 switch (k) { 344 case "colorArray": 345 program.uniforms.uColorStops.value = v; 346 break; 347 case "backgroundColor":
348 program.uniforms.uBackgroundColor.value = v; 349 break; 350 case "speed": 351 program.uniforms.uSpeed.value = v; 352 break; 353 case "intensity": 354 program.uniforms.uIntensity.value = v; 355 break; 356 case "noise": 357 program.uniforms.uNoise.value = v; 358 break; 359 case "scale": 360 program.uniforms.uScale.value = v; 361 break; 362 case "angle": 363 program.uniforms.uAngle.value = v; 364 break; 365 case 'progress': 366 if (program.uniforms.uSpeed.value === 0) { 367 program.uniforms.uProgress.value = v; 368 } 369 break; 370 case 'mouseInteractive': 371 if (v) { 372 program.uniforms.uInteractive.value = 1; 373 this.$element[0].addEventListener('mousemove', this.updateMousePosition); 374 } else { 375 program.uniforms.uInteractive.value = 0; 376 this.$element[0].removeEventListener('mousemove', this.updateMousePosition); 377 } 378 break; 379 case 'static': 380 if (!v) { 381 const speedSetting = this.getElementSettings('section_fluid_speed'); 382 program.uniforms.uSpeed.value = speedSetting ? normalizeSettings({ 383 speed: speedSetting 384 }) : 0.01; 385 } else { 386 program.uniforms.uSpeed.value = 0; 387 } 388 break; 389 case 'offsetX': 390 program.uniforms.uOffsetX.value = v; 391 break; 392 case 'offsetY': 393 program.uniforms.uOffsetY.value = v; 394 break; 395 } 396 } 397 } 398 } 399 onElementChange(propertyName) { 400 if (this.getElementSettings('section_fluid_on') !== 'yes' || ['animation-1', 'animation-2', 'animation-3', 'animation-4', 'animation-5'].some(suffix => propertyName.endsWith(suffix)) // Css based animations 401 ) { 402 return; 403 } 404 clearTimeout(this.updateTimeout); 405 this.updateTimeout = setTimeout(() => { 406 this.updateSettings(propertyName); 407 }, 50); 408 } 409 } 410 jQuery(window).on('elementor/frontend/init', () => { 411 const addHandler = $element => { 412 elementorFrontend.elementsHandler.addHandler(animatedBackground, { 413 $element 414 }); 415 }; 416 elementorFrontend.hooks.addAction('frontend/element_ready/section', addHandler); 417 elementorFrontend.hooks.addAction('frontend/element_ready/container', addHandler); 418 }); 419}, false);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.