Graphic Designer

Voir mes créations
Scroll
Ils me font confiance

Collaborations

Créateur YouTube
Travaillons ensemble

Contact

/* ══ MINIATURE BORDER GLOW ══ */ (function() { const DURATION = 8000; // 8s par tour, lent const active = new Map(); // item → {progress, last, rafId} function perimeterPoint(t, w, h, r) { const sides = [w-2*r, h-2*r, w-2*r, h-2*r]; const arcs = 4 * (Math.PI/2 * r); const total = sides.reduce((a,b)=>a+b,0) + arcs; let dist = t * total; const segs = [ { len: w-2*r, type:'line', x0:r, y0:0, dx:1, dy:0 }, { len:Math.PI/2*r, type:'arc', cx:w-r, cy:r, a0:-Math.PI/2, da:Math.PI/2 }, { len: h-2*r, type:'line', x0:w, y0:r, dx:0, dy:1 }, { len:Math.PI/2*r, type:'arc', cx:w-r, cy:h-r, a0:0, da:Math.PI/2 }, { len: w-2*r, type:'line', x0:w-r, y0:h, dx:-1, dy:0 }, { len:Math.PI/2*r, type:'arc', cx:r, cy:h-r, a0:Math.PI/2, da:Math.PI/2 }, { len: h-2*r, type:'line', x0:0, y0:h-r, dx:0, dy:-1 }, { len:Math.PI/2*r, type:'arc', cx:r, cy:r, a0:Math.PI, da:Math.PI/2 }, ]; for (const s of segs) { if (dist <= s.len) { const f = dist/s.len; if (s.type==='line') return { x: s.x0+s.dx*dist, y: s.y0+s.dy*dist }; else { const a=s.a0+s.da*f; return { x:s.cx+Math.cos(a)*r, y:s.cy+Math.sin(a)*r }; } } dist -= s.len; } return {x:r,y:0}; } function drawGlow(canvas, ctx, progress) { const w = canvas.width, h = canvas.height, r = 10; ctx.clearRect(0, 0, w, h); const pt = perimeterPoint(progress, w, h, r); const grd = ctx.createRadialGradient(pt.x, pt.y, 0, pt.x, pt.y, 80); grd.addColorStop(0, "rgba(255,255,255,0.95)"); grd.addColorStop(0.15, "rgba(200,225,255,0.7)"); grd.addColorStop(0.4, "rgba(153,183,220,0.35)"); grd.addColorStop(1, "rgba(153,183,220,0)"); ctx.save(); ctx.beginPath(); ctx.moveTo(r,0); ctx.lineTo(w-r,0); ctx.arcTo(w,0,w,r,r); ctx.lineTo(w,h-r); ctx.arcTo(w,h,w-r,h,r); ctx.lineTo(r,h); ctx.arcTo(0,h,0,h-r,r); ctx.lineTo(0,r); ctx.arcTo(0,0,r,0,r); ctx.closePath(); ctx.lineWidth = 4; ctx.strokeStyle = grd; ctx.stroke(); ctx.restore(); } function startGlow(item) { if (active.has(item)) return; const canvas = document.createElement("canvas"); canvas.style.cssText = "position:absolute;inset:-2px;width:calc(100% + 4px);height:calc(100% + 4px);border-radius:12px;pointer-events:none;z-index:3;"; item.appendChild(canvas); const ctx = canvas.getContext("2d"); canvas.width = item.offsetWidth + 4; canvas.height = item.offsetHeight + 4; let progress = Math.random(); // départ aléatoire let last = null; function loop(ts) { if (!last) last = ts; const dt = ts - last; last = ts; progress = (progress + dt / DURATION) % 1; drawGlow(canvas, ctx, progress); const state = active.get(item); if (state) { state.rafId = requestAnimationFrame(loop); } } const rafId = requestAnimationFrame(loop); active.set(item, { rafId }); } function stopGlow(item) { const state = active.get(item); if (!state) return; cancelAnimationFrame(state.rafId); active.delete(item); const canvas = item.querySelector("canvas.glow-canvas"); // remove added canvas item.querySelectorAll("canvas").forEach(c => c.remove()); } // Expose pour appel externe window.startGlowOn = startGlow; })();