Ils me font confiance
Collaborations
Mon travail
Galerie de miniatures
✕
Créateur YouTube
/* ══ 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;
})();