Artoke
02

Canvas 2D · Eased Highlight

노드 호버 하이라이트

노드에 마우스를 올려보세요 · 드래그로 회전

↑ 노드에 마우스를 올리면 연결된 그룹이 밝아집니다 · 드래그로 회전, 휠로 확대

마우스를 노드에 올리면 그 노드와 연결된 그룹만 스르륵 밝아지고 나머지는 어둡게 가라앉습니다. 핵심은 '이징(easing)' — 밝기를 즉시 바꾸지 않고 매 프레임 목표값으로 조금씩 수렴시켜, 켜짐/꺼짐이 부드럽게 흐릅니다.

node-hover.ts — 핵심 패턴 (distilled)
// 캔버스 노드 그래프의 "이징(easing) 호버 하이라이트".
// 매 프레임: 커서 아래 노드를 찾고, 모든 노드의 밝기를 목표값으로 부드럽게
// 수렴시킵니다 — 호버 노드와 그 이웃은 1로, 나머지는 어두운 바닥값으로.
// 딱 켜지고 꺼지는 게 아니라 스르륵 밝아졌다 사라집니다.

const EASE = 0.1;   // 프레임당 blend 비율 (작을수록 더 부드럽게)
const DIM = 0.16;   // 호버 안 된 노드의 최소 밝기(바닥값)

let hovered = null;

canvas.addEventListener("pointermove", (e) => {
  const rect = canvas.getBoundingClientRect();
  const px = e.clientX - rect.left;
  const py = e.clientY - rect.top;
  let best = null;
  let bestD = Infinity;
  for (const n of nodes) {
    const dx = n.sx - px; // n.sx / n.sy = 노드의 화면 좌표
    const dy = n.sy - py;
    const d = dx * dx + dy * dy;
    const hit = (n.radius + 8) ** 2; // 반지름 + 여유 8px
    if (d < hit && d < bestD) { bestD = d; best = n; }
  }
  hovered = best;
});

function draw() {
  for (const n of nodes) {
    // 호버 노드거나 그 이웃이면 1, 아니면 0을 목표로
    const lit =
      !hovered || n === hovered || neighbours.get(hovered.id)?.has(n.id) ? 1 : 0;
    n.cur += (lit - n.cur) * EASE;          // 목표값으로 이징
    const alpha = DIM + (1 - DIM) * n.cur;  // 바닥값 → 최대 밝기
    drawNode(n, alpha);
  }
  requestAnimationFrame(draw);
}