Médias

/* HEATLIFT GLOBAL SCRIPTS — HTHP cycle animation */ (function () { 'use strict'; const SELECTOR = '[data-hl-cycle]'; const initialized = new WeakSet(); const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); const ORIGINAL_WIDTH = 3095; const ORIGINAL_HEIGHT = 1055; const ORIGINAL_POINTS = [ { x: 727, y: 989 }, { x: 1149, y: 989 }, { x: 1149, y: 579 }, { x: 1973, y: 579 }, { x: 1973, y: 101 }, { x: 1588, y: 101 }, { x: 1588, y: 322 }, { x: 727, y: 322 }, { x: 727, y: 989 } ]; const segments = []; let totalLength = 0; for (let index = 0; index < ORIGINAL_POINTS.length - 1; index += 1) { const start = ORIGINAL_POINTS[index]; const end = ORIGINAL_POINTS[index + 1]; const length = Math.hypot(end.x - start.x, end.y - start.y); totalLength += length; segments.push({ start, end, length, endDistance: totalLength }); } function createTrail(container, xPercent, yPercent) { const trail = document.createElement('span'); trail.className = 'hl-hthp-cycle__trail'; trail.style.left = xPercent + '%'; trail.style.top = yPercent + '%'; container.appendChild(trail); window.setTimeout(function () { trail.style.opacity = '0'; window.setTimeout(function () { trail.remove(); }, 520); }, 420); } function initializeCycle(container) { if (!container || initialized.has(container) || reducedMotion.matches) return; const image = container.querySelector('.hl-hthp-cycle__image'); if (!image) return; initialized.add(container); container.querySelectorAll('.hl-hthp-cycle__moving-point, .hl-hthp-cycle__trail').forEach(function (node) { node.remove(); }); const point = document.createElement('span'); point.className = 'hl-hthp-cycle__moving-point'; point.setAttribute('aria-hidden', 'true'); container.appendChild(point); let distance = 0; let previousTime = 0; let previousTrailTime = 0; const speed = 190; // Original-image pixels per second. function render(timestamp) { if (!container.isConnected || reducedMotion.matches) { point.remove(); initialized.delete(container); return; } if (document.hidden) { previousTime = timestamp; window.requestAnimationFrame(render); return; } if (!previousTime) previousTime = timestamp; const deltaSeconds = Math.min((timestamp - previousTime) / 1000, 0.05); previousTime = timestamp; distance = (distance + speed * deltaSeconds) % totalLength; let segment = segments[segments.length - 1]; for (const candidate of segments) { if (distance <= candidate.endDistance) { segment = candidate; break; } } const segmentStart = segment.endDistance - segment.length; const progress = (distance - segmentStart) / segment.length; const x = segment.start.x + (segment.end.x - segment.start.x) * progress; const y = segment.start.y + (segment.end.y - segment.start.y) * progress; const xPercent = (x / ORIGINAL_WIDTH) * 100; const yPercent = (y / ORIGINAL_HEIGHT) * 100; point.style.left = xPercent + '%'; point.style.top = yPercent + '%'; if (timestamp - previousTrailTime > 110) { createTrail(container, xPercent, yPercent); previousTrailTime = timestamp; } window.requestAnimationFrame(render); } const start = function () { window.requestAnimationFrame(render); }; if (image.complete) start(); else image.addEventListener('load', start, { once: true }); } function initializeAll(scope) { const root = scope || document; if (root.matches && root.matches(SELECTOR)) initializeCycle(root); root.querySelectorAll(SELECTOR).forEach(initializeCycle); } function boot() { initializeAll(document); // Supports modules inserted or refreshed by the Divi Visual Builder. const observer = new MutationObserver(function (mutations) { for (const mutation of mutations) { mutation.addedNodes.forEach(function (node) { if (node.nodeType === Node.ELEMENT_NODE) initializeAll(node); }); } }); observer.observe(document.body, { childList: true, subtree: true }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', boot, { once: true }); } else { boot(); } }());