| Current Path : /home/happyrenas/find.myreco.online/js/ |
Linux webd005.cluster105.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 |
| Current File : /home/happyrenas/find.myreco.online/js/neige.js |
(function snowFX(){
if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
if (localStorage.getItem('snowfx') === '0') return;
const boot = () => {
const canvas = document.createElement('canvas');
canvas.id = 'snowfx';
canvas.style.cssText = [
'position:fixed','inset:0','width:100%','height:100%',
'pointer-events:none','z-index:2147483647',
'opacity:.28',
'mix-blend-mode:difference'
].join(';') + ';';
const ctx = canvas.getContext('2d', { alpha:true });
(document.documentElement || document.body).appendChild(canvas);
let W=1,H=1,DPR=1, parts=[], raf=0, t0=0;
let windPhase = Math.random()*Math.PI*2;
const rand=(a,b)=>a+Math.random()*(b-a);
function resize(){
DPR = Math.min(2, window.devicePixelRatio || 1);
W = Math.max(1, window.innerWidth);
H = Math.max(1, window.innerHeight);
canvas.width = Math.floor(W*DPR);
canvas.height = Math.floor(H*DPR);
ctx.setTransform(DPR,0,0,DPR,0,0);
init();
}
function init(){
parts = [];
const n = Math.max(22, Math.min(65, Math.floor((W*H)/52000))); // léger
for(let i=0;i<n;i++){
const depth = Math.random(); // 0..1
const r = rand(1.0, 3.2) * (0.55 + depth); // taille
parts.push({
x: rand(0,W),
y: rand(-H,H),
r,
depth,
vy: rand(10, 26) * (0.35 + depth),
vx: rand(-7, 7) * (0.25 + depth),
a: rand(0.20, 0.40) * (0.6 + depth),
tw: rand(0, Math.PI*2),
tws: rand(0.6, 1.6),
rot: rand(0, Math.PI*2),
vr: rand(-0.8, 0.8), // rotation lente
arms: (Math.random() < 0.65) ? 3 : 0 // certains ont des “branches”
});
}
}
function drawFlake(p, alpha){
// petit noyau
ctx.beginPath();
ctx.fillStyle = `rgba(255,255,255,${alpha})`;
ctx.arc(p.x, p.y, p.r*0.55, 0, Math.PI*2);
ctx.fill();
if (!p.arms) return;
// branches fines (style “étoile minimaliste”)
const len = p.r * (1.3 + p.depth*0.5);
const lw = Math.max(0.6, p.r*0.22);
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.rot);
ctx.lineWidth = lw;
ctx.lineCap = 'round';
ctx.strokeStyle = `rgba(255,255,255,${alpha*0.85})`;
ctx.beginPath();
for(let i=0;i<p.arms;i++){
const a = (Math.PI*2) * (i/p.arms);
// branche principale
ctx.moveTo(0,0);
ctx.lineTo(Math.cos(a)*len, Math.sin(a)*len);
// 2 petites “barbes” sur la branche (subtil)
const bx = Math.cos(a)*len*0.65;
const by = Math.sin(a)*len*0.65;
const b1 = a + 0.55;
const b2 = a - 0.55;
ctx.moveTo(bx,by);
ctx.lineTo(bx + Math.cos(b1)*len*0.22, by + Math.sin(b1)*len*0.22);
ctx.moveTo(bx,by);
ctx.lineTo(bx + Math.cos(b2)*len*0.22, by + Math.sin(b2)*len*0.22);
}
ctx.stroke();
ctx.restore();
}
function step(ts){
if(!t0) t0 = ts;
const dt = Math.min(0.032, (ts - t0)/1000);
t0 = ts;
windPhase += dt*0.22;
const wind = Math.sin(windPhase) * 16;
ctx.clearRect(0,0,W,H);
for(const p of parts){
p.tw += dt*p.tws;
p.rot += dt*p.vr * (0.5 + p.depth);
const twinkle = 0.72 + 0.28*Math.sin(p.tw);
p.x += (p.vx + wind*(0.10 + p.depth*0.22))*dt;
p.y += p.vy*dt;
if(p.y > H + 12){ p.y = -12; p.x = rand(0,W); }
if(p.x < -25) p.x = W + 25;
if(p.x > W + 25) p.x = -25;
const alpha = p.a * twinkle;
// petit halo très doux pour “flocon”
ctx.beginPath();
ctx.fillStyle = `rgba(255,255,255,${alpha*0.25})`;
ctx.arc(p.x, p.y, p.r*1.25, 0, Math.PI*2);
ctx.fill();
drawFlake(p, alpha);
}
raf = requestAnimationFrame(step);
}
resize();
raf = requestAnimationFrame(step);
window.addEventListener('resize', resize, {passive:true});
document.addEventListener('visibilitychange', () => {
if(document.hidden) cancelAnimationFrame(raf);
else { t0=0; resize(); raf=requestAnimationFrame(step); }
});
};
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
else boot();
})();