diff --git a/public/particle-bg.js b/public/particle-bg.js index 3b886fd..29d6338 100644 --- a/public/particle-bg.js +++ b/public/particle-bg.js @@ -1,27 +1,28 @@ /** * Rete di particelle + linee (canvas #particleCanvas). - * Deve stare DENTRO il contenitore della pagina (es. .nx-grid-bg), non dietro body, - * altrimenti lo sfondo opaco della pagina lo copre. + * Limitato al viewport (non all’altezza documento): evita canvas giganti che + * bloccano lo scroll sulla home lunga. */ (function () { if (typeof window === 'undefined') return; var canvas = document.getElementById('particleCanvas'); if (!canvas) return; - var ctx = canvas.getContext('2d'); + var ctx = canvas.getContext('2d', { alpha: true }); if (!ctx) return; var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches; - var particles = []; var mouse = { x: null, y: null, radius: 150 }; var raf = 0; + var running = false; + var cachedW = 0; + var cachedH = 0; + var scrollPauseTimer = 0; - function canvasSize() { - var p = canvas.parentElement; - if (!p) return { w: 0, h: 0 }; - var w = Math.max(1, Math.floor(p.clientWidth)); - var h = Math.max(1, Math.floor(p.clientHeight)); + function viewportSize() { + var w = Math.max(1, Math.floor(window.innerWidth || document.documentElement.clientWidth || 1)); + var h = Math.max(1, Math.floor(window.innerHeight || document.documentElement.clientHeight || 1)); return { w: w, h: h }; } @@ -29,8 +30,8 @@ this.x = Math.random() * w; this.y = Math.random() * h; this.size = Math.random() * 2 + 1; - this.speedX = (Math.random() - 0.5) * 1.5; - this.speedY = (Math.random() - 0.5) * 1.5; + this.speedX = (Math.random() - 0.5) * 1.2; + this.speedY = (Math.random() - 0.5) * 1.2; } Particle.prototype.draw = function () { @@ -58,46 +59,55 @@ var fx = dx / distance; var fy = dy / distance; var force = (mouse.radius - distance) / mouse.radius; - this.x -= fx * force * 5; - this.y -= fy * force * 5; + this.x -= fx * force * 4; + this.y -= fy * force * 4; } }; function init() { - var sz = canvasSize(); + var sz = viewportSize(); var w = sz.w; var h = sz.h; - if (w < 8 || h < 8) return; + cachedW = w; + cachedH = h; - var dpr = Math.min(window.devicePixelRatio || 1, 2); + var dpr = Math.min(window.devicePixelRatio || 1, 1.5); canvas.width = Math.floor(w * dpr); canvas.height = Math.floor(h * dpr); + canvas.style.width = w + 'px'; + canvas.style.height = h + 'px'; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); particles = []; - var n = Math.floor((w * h) / 9000); - if (n > 130) n = 130; - if (n < 45) n = 45; + var area = w * h; + var n = Math.floor(area / 14000); + if (n > 80) n = 80; + if (n < 28) n = 28; + if (w < 768) { + n = Math.min(n, 40); + } for (var i = 0; i < n; i++) { particles.push(new Particle(w, h)); } } - function connect(w, h) { + function connect(w) { + var maxDist = w < 768 ? 110 : 140; var a; var b; var dx; var dy; var distance; var opacity; - for (a = 0; a < particles.length; a++) { - for (b = a + 1; b < particles.length; b++) { + var len = particles.length; + for (a = 0; a < len; a++) { + for (b = a + 1; b < len; b++) { dx = particles[a].x - particles[b].x; dy = particles[a].y - particles[b].y; distance = Math.sqrt(dx * dx + dy * dy); - if (distance < 150) { - opacity = (1 - distance / 150) * 0.22; - ctx.strokeStyle = 'rgba(59, 130, 246, ' + opacity + ')'; + if (distance < maxDist) { + opacity = (1 - distance / maxDist) * 0.2; + ctx.strokeStyle = 'rgba(59, 130, 246,' + opacity + ')'; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(particles[a].x, particles[a].y); @@ -109,9 +119,9 @@ } function frame() { - var sz = canvasSize(); - var w = sz.w; - var h = sz.h; + if (!running) return; + var w = cachedW; + var h = cachedH; ctx.clearRect(0, 0, w, h); var i; @@ -119,29 +129,33 @@ particles[i].update(w, h); particles[i].draw(); } - connect(w, h); + connect(w); raf = requestAnimationFrame(frame); } - function syncCanvasCssSize() { - var sz = canvasSize(); - canvas.style.width = sz.w + 'px'; - canvas.style.height = sz.h + 'px'; + function start() { + if (reduced || document.hidden || running || !particles.length) return; + running = true; + raf = requestAnimationFrame(frame); } - function onResize() { - cancelAnimationFrame(raf); - syncCanvasCssSize(); - init(); - if (!reduced && particles.length) { - raf = requestAnimationFrame(frame); + function stop() { + running = false; + if (raf) { + cancelAnimationFrame(raf); + raf = 0; } } + function onResize() { + stop(); + init(); + start(); + } + function setMouseFromEvent(e) { - var rect = canvas.getBoundingClientRect(); - mouse.x = e.clientX - rect.left; - mouse.y = e.clientY - rect.top; + mouse.x = e.clientX; + mouse.y = e.clientY; } window.addEventListener( @@ -152,22 +166,26 @@ { passive: true }, ); - var parent = canvas.parentElement; - if (parent) { - var ro = new ResizeObserver(onResize); - ro.observe(parent); - } + window.addEventListener( + 'scroll', + function () { + // Libera il main thread durante lo scroll; riprende subito dopo. + stop(); + if (scrollPauseTimer) window.clearTimeout(scrollPauseTimer); + scrollPauseTimer = window.setTimeout(function () { + start(); + }, 120); + }, + { passive: true }, + ); + + document.addEventListener('visibilitychange', function () { + if (document.hidden) stop(); + else start(); + }); window.addEventListener('resize', onResize, { passive: true }); - syncCanvasCssSize(); init(); - - if (reduced) { - return; - } - - if (particles.length) { - raf = requestAnimationFrame(frame); - } + start(); })(); diff --git a/src/components/ChatGateModal.astro b/src/components/ChatGateModal.astro index a7e144c..82cf19c 100644 --- a/src/components/ChatGateModal.astro +++ b/src/components/ChatGateModal.astro @@ -1,6 +1,11 @@ --- -import { chat } from '../data/home'; +import { getChat } from '../data/home'; +import type { SupportedLocale } from '../data/home/navigation'; +const path = Astro.url.pathname; +const localeMatch = path.match(/^\/(en|th)(\/|$)/); +const currentLocale = (localeMatch?.[1] ?? 'it') as SupportedLocale; +const chat = getChat(currentLocale); const pc = chat.prechat; const hasFormspree = typeof pc.actionUrl === 'string' && pc.actionUrl.length > 0; diff --git a/src/components/CookieConsent.astro b/src/components/CookieConsent.astro index bced16a..9274341 100644 --- a/src/components/CookieConsent.astro +++ b/src/components/CookieConsent.astro @@ -1,5 +1,18 @@ --- -import { cookieConsentMeta, cookieCategories } from '../data/cookie-consent'; +import { + cookieConsentMeta, + getCookieCategories, + getCookieConsentUi, +} from '../data/cookie-consent'; +import type { SupportedLocale } from '../data/home/navigation'; + +const path = Astro.url.pathname; +const localeMatch = path.match(/^\/(en|th)(\/|$)/); +const currentLocale = (localeMatch?.[1] ?? 'it') as SupportedLocale; +const cookieCategories = getCookieCategories(currentLocale); +const ui = getCookieConsentUi(currentLocale); +const cookiesHref = + currentLocale === 'it' ? '/cookies' : `/${currentLocale}/cookies`; const model = { storageKey: cookieConsentMeta.storageKey, @@ -28,15 +41,14 @@ const model = { id="nx-cc-banner-title" class="text-sm font-semibold tracking-tight text-nx-fg" > - Utilizziamo cookie e memorizzazione locale + {ui.bannerTitle}
- Versione informativa v{cookieConsentMeta.policyVersion}. Puoi modificare - le scelte in qualsiasi momento dal footer. + {ui.dialogIntroBefore}{cookieConsentMeta.policyVersion}{ui.dialogIntroAfter}