Communitygithub.com

스크롤 모션 그래픽

캔버스 필름이 스크롤 위치에 따라 scrub되는 스크롤 기반 모션 그래픽 섹션(sticky scrollytelling 스테이지, 스크롤/드래그/키보드로 회전하는 3D 스토리 드럼 등)을 구축하거나 수정할 때 사용합니다. 기존 스크롤 애니메이션이 버벅이거나, 휠을 가로채거나, CPU를 낭비하거나, prefers-reduced-motion을 무시할 때도 사용합니다.

스크롤 모션 그래픽란 무엇인가요?

이 스킬은 스크롤 위치를 유일한 시간 축으로 사용하여 캔버스 기반 모션 그래픽을 구현하는 완전한 방법론을 제공합니다. 페이지 하이재킹 없이 부드러운 scrub 경험을 제공하며, 모든 픽셀, 캡션, 회전을 스크롤 진행률 p의 순수 함수로 만드는 것이 핵심입니다. Claude Code, Cursor, Codex와 같은 AI 에이전트가 이 스킬을 사용하면 스크롤 연동 스토리텔링, 3D 드럼, 스크롤 기반 캔버스 애니메이션을 올바르게 구축할 수 있습니다. 이 방법은 CSS sticky를 통한 피닝, requestAnimationFrame의 효율적인 유휴 처리, DOM 기반 캡션, prefers-reduced-motion 존중 등 12가지 엄격한 규칙을 따릅니다. 또한 완전한 데모 파일(assets/demo.html)과 엔진(assets/scroll-motion.js), React 래퍼(assets/ScrollFilm.jsx, assets/StoryDrum.jsx)를 포함하여 즉시 시작할 수 있습니다.

지원 대상✓Claude Code~Codex CLI✓Cursor✓OpenCode
npx skills add https://github.com/shubham001312/imutechz-skills/tree/HEAD/skills/scroll-motion-graphics

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

스크롤 모션 그래픽은(는) 무엇을 하나요?

스크롤 위치에 의해 구동되는 캔버스 타임라인: 고정된 스테이지(pinned stage), 진행률의 순수 함수인 릴(reels), 그리고 그림이 절대 닿지 않는 캡션. 이 방법은 ImuTechz 홈페이지의 스토리 드럼, R&D 드럼, Founder 경로 필름을 구동합니다. 또한 assets/demo.html에 있는 5릴 데모도 지원합니다.

전체 기술은 한 문장으로 요약됩니다. 스크롤 위치가 유일한 시계입니다. 스크롤 위치를 p ∈ [0, 1]에 매핑하고, 모든 픽셀, 캡션, 회전을 p의 함수로 만드세요.

좋은 예시의 특징

  • 비디오처럼 scrub됩니다. 앞으로 스크롤하면 영상이 재생됩니다. 뒤로 스크롤하면 프레임 단위로 되감깁니다. 중간에 멈추면 의미 있는 프레임이 남습니다.
  • 페이지가 절대 하이재킹되지 않습니다. 휠, 트랙패드, 터치, 키보드 모두 다른 곳과 동일하게 페이지를 움직입니다. 섹션은 그저 높을 뿐입니다.
  • 텍스트는 항상 읽을 수 있습니다. 캡션은 카드 위의 실제 DOM 텍스트입니다. 그림은 캡션이 남긴 공간에 배치되며, 캔버스는 안전망으로 주변을 클리핑합니다.
  • 단순한 쇼가 아니라 컨트롤입니다. 스토리 드럼의 면(face)은 링크입니다. 레일, 화살표 버튼, 화살표 키, 마우스 드래그 모두 페이지를 스크롤하여 탐색하므로 스크롤과 드럼이 절대 불일치하지 않습니다.
  • 유휴 페이지는 리소스를 소모하지 않습니다. p가 안정되거나 섹션이 뷰포트를 벗어나면 requestAnimationFrame이 실행되지 않습니다.
  • Reduced motion을 존중합니다. 스무딩, 중간 드럼 롤, 캡션 진입 애니메이션이 없습니다. 모든 콘텐츠는 그대로 표시됩니다.
  • 360px에서 1920px 너비까지, 라이트/다크 모드, DPR 1과 2에서도 문제없이 작동합니다.

엄격한 규칙

  1. p는 스크롤 위치에서만 오며, 절대 시계에서 오지 않습니다. 릴 내부에서 performance.now(), Date, CSS 애니메이션, setInterval을 사용하지 마십시오. 목표 p를 향한 lerp 스무딩은 최종 프레임으로 수렴하므로 허용됩니다.
  2. 릴은 순수 함수입니다: draw(ctx, t, env). 릴은 프레임 간에 상태를 유지하지 않으며 Math.random()을 절대 호출하지 않습니다. 대신 시드된 hash(i)를 사용하십시오. 동일한 (t, env)는 동일한 픽셀을 그려야 합니다.
  3. CSS로 피닝하고, JS로 하지 마십시오. position: relative; height: N×vh인 긴 트랙을 만들고 그 안에 position: sticky; top: 0; height: 100svh인 스테이지를 배치하십시오. 스테이지에 position: fixed를 설정하지 말고, body를 잠그지 말며, 트랙의 조상에 overflow: hidden|auto|clip을 설정하지 마십시오.
  4. 절대 입력을 가로채지 마십시오. 휠이나 터치에 preventDefault를 사용하지 말고, html이나 body에 overflow: hidden을 설정하지 말며, 트랙에 scroll snapping을 사용하지 마십시오. 포커스된 드럼만 화살표 키를 처리할 수 있으며, 그 방식은 페이지를 스크롤하는 것입니다.
  5. 스크롤하여 탐색하십시오. 모든 버튼, 레일 아이템, 키, 앵커는 window.scrollY를 변경합니다. p나 회전을 직접 설정하지 마십시오. 프로그래매틱 점프에는 behavior: "instant"를 사용하십시오. "auto"는 페이지의 CSS scroll-behavior: smooth를 따르므로 애니메이션될 수 있습니다.
  6. 텍스트는 DOM에 있습니다. 캡션, 제목, 링크는 HTML입니다. 캔버스 텍스트는 연도, 축 틱, 단계 이름과 같은 장식용 레이블로 제한됩니다.
  7. 매 프레임 캡션을 측정하고 그림을 캡션 밖에 유지하십시오. 각 캡션과 HUD 요소는 keep-out 영역(data-keep)입니다. 릴은 env.free 내부에 배치되며, 엔진은 even-odd 클립으로 keep-out 영역을 클리핑합니다.
  8. 절대 두 개의 캡션을 동시에 표시하지 마십시오. 캡션 윈도우는 각 경계에 간격을 두고 릴 내부에 위치하며, 릴은 해당 간격 내에서 크로스페이드됩니다.
  9. 유휴 상태가 되면 루프를 중지하십시오. 섹션이 뷰포트 근처에 있을 때만(IntersectionObserver) 스크롤 또는 리사이즈 시 rAF를 시작하고, p가 목표와 같아지면 중지하십시오.
  10. 캔버스는 min(devicePixelRatio, 2)로 스테이지 크기에 맞춰집니다. 매 프레임 setTransform(dpr, …)을 호출하고 매 프레임 지웁니다.
  11. 색상은 CSS 커스텀 프로퍼티에서 가져옵니다. 릴에 라이트 모드 팔레트를 하드코딩하지 마십시오. prefers-color-scheme 변경 시 팔레트를 다시 읽으십시오.
  12. prefers-reduced-motion: reduce를 존중하십시오. 스무딩을 사용하지 말고, 드럼이 면에서 면으로 스냅되게 하며, 캡션 진입 애니메이션을 끄십시오. 사용자가 구동하므로 프레임은 여전히 스크롤을 따릅니다.

빌드 순서

다음 순서대로 진행하십시오. 각 단계는 다음 단계 전에 테스트 가능해야 합니다.

  1. 콘텐츠 먼저. 챕터를 작성하십시오: 각 챕터에 대해 kicker, 제목, 한두 문장, 선택적 링크. 릴 개수(37개)를 선택하고 각 릴에 약 80100svh의 스크롤을 할당하십시오.
  2. 트랙과 스테이지. 내부에 sticky 100svh 스테이지가 있는 긴 섹션을 추가하고, JS 없이 피닝되는지 확인하십시오(layout-and-captions 참조).
  3. Scrub 엔진. ScrollMotion.scrub 또는 film을 연결하고(engine 참조) p를 로그로 출력하십시오. 핀 시작에서 0, 핀 끝에서 1을 읽고 양방향으로 움직이는지 확인하십시오.
  4. DOM의 캡션과 HUD. 브레이크포인트별로 배치하고 data-keep으로 표시한 다음 엔진이 p에서 불투명도를 구동하게 하십시오.
  5. 릴을 하나씩. env.free 내부에 draw(ctx, t, env)를 작성하고(drawing 참조), 다음 릴을 작성하기 전에 앞뒤로 scrub하십시오.
  6. 모션 문법. 진입, 유지, 종료 엔벨로프, stagger, 머뭄(dwell), 크로스페이드를 추가하십시오(motion-grammar 참조).
  7. 상호작용 (드럼인 경우). 면 링크, 레일, 이전/다음 버튼, 키, 드래그를 추가하고 모두 스크롤로 탐색하게 하십시오.
  8. 성능 및 접근성 패스. 유휴 루프, DPR, reduced motion, 포커스 순서, 스크린 리더 텍스트, 다크 모드를 다루십시오(performance-and-a11y 참조).
  9. 검증. 360, 390, 414, 768, 1024, 1280, 1440, 1920에서 헤드리스 스크립트로 확인하십시오(verification 참조). 모든 검사가 통과할 때까지 완료되었다고 하지 마십시오.

결정 체크리스트

캔버스 필름 vs DOM/CSS 변환?

  • 많은 작은 움직이는 부품, 선을 그리는 요소, 입자, 차트 → 캔버스 필름 (ScrollMotion.film).
  • 소수의 카드, 이미지, 텍스트 패널 → scrub으로 구동되는 DOM 변환 (드럼이 하나의 예).
  • 실제 3D 메시나 셰이더 → 이 스킬만으로는 부족합니다. WebGL을 사용하되 규칙 15, 912를 지키십시오.

핀 모드 vs 뷰 모드?

  • 섹션이 스토리를 재생하는 동안 화면을 고정해야 함 → mode: "pin" (긴 트랙과 sticky 스테이지).
  • 효과가 콘텐츠가 지나감에 따라 따라 움직임 (마키나 parallax 등) → mode: "view", 피닝 없음.

트랙 높이는 얼마나?

  • 필름의 경우 n × 80–100svh + 100svh, 드럼의 경우 n × 70vh + 100vh를 사용하십시오. 테스트 리더가 "너무 빠르다"고 하면 높이를 추가하십시오. 휠을 가로채서 속도를 늦추지 마십시오.

캡션은 어디에?

  • 데스크톱(≥760px): 그림 옆(왼쪽 또는 오른쪽 카드) 또는 넓은 하단 카드. 휴대폰: 항상 하단 시트, 그림은 그 위에.
  • 고정된 사이트 헤더가 있는 경우 HUD와 드럼이 헤더를 피할 수 있도록 --sm-nav-h를 설정하십시오.

드럼이 필요한가?

  • 챕터가 사용자가 이동하고 싶어할 것들(페이지, 제품, 섹션)일 때 드럼을 사용하십시오. 그렇지 않으면 필름만 사용하십시오.

실패 모드 및 수정

증상원인수정
스테이지가 피닝되지 않고 스크롤됨조상에 overflow: hidden/auto/clip이 있거나 스테이지에 top이 없음overflow 제거(필요시 body에 overflow-x: clip 사용)하고 top: 0 설정
애니메이션이 앞으로만 재생되거나, 스크롤 업 시 점프프레임 간에 상태가 누적되었거나, 릴에 시계 또는 Math.random이 있음릴을 t의 순수 함수로 만들고, 난수는 hash(i) 사용
그림이 캡션 아래로 그림릴이 전체 스테이지에 배치됨env.free 안에 배치하고, 캡션에 data-keep 유지, 엔진이 클리핑하도록 함
페이드 중 캡션 상자가 잘못된 위치에서 측정됨getBoundingClientRect 사용(변환 포함)레이아웃 상자 측정(offsetLeft/Top/Width/Height, boxIn 참조)
경계에서 두 캡션이 겹침캡션 윈도우가 서로 닿음캡션을 1 − cross에서 페이드 아웃하고 cross에서 페이드 인; 릴은 간격에서 크로스페이드
유휴 페이지에서 팬이 돌아감rAF 루프가 멈추지 않음cur === target일 때 중지; IntersectionObserver로 게이트
휴대폰에서 흐릿한 캔버스 / 4K에서 느림캔버스가 CSS 크기이거나 DPR 제한 없음width = W × min(dpr, 2) 및 setTransform(dpr, 0, 0, dpr, 0, 0) 사용
레일 클릭 후 드럼과 페이지 불일치컨트롤이 회전을 직접 설정함모든 컨트롤은 scrollToProgress 호출; 회전은 항상 p에서만 옴
드래그 시 버벅임 후 되돌아감페이지에 scroll-behavior: smooth가 있어 scrollTo(x, y)가 애니메이션됨드래그 중에는 scrollTo({ top, behavior: "instant" }) 사용
드래그 후 면 클릭 시 링크 열림드래그를 끝내는 클릭이 발생함4px 이상 움직인 드래그 후 캡처 단계 클릭 하나를 삼킴
모바일에서 URL 바가 숨을 때 100vh 점프스테이지에 vh 사용스테이지에 100svh 사용; 스테이지 자체 높이로 p 계산
다크 모드에서 라이트 모드 그림 표시하드코딩된 색상readPalette로 --sm-* 토큰 읽기; 색상 테마 변경 시 다시 읽기
드럼 뒷면이 비침backface-visibility: hidden 누락모든 면에 -webkit- 접두사와 함께 설정
드럼 면 썸네일이 잘못된 크기로 그려짐3D 변환된 면의 예상 직사각형 사용clientWidth/clientHeight로 크기 지정

파일

데모에서 시작하십시오: 열고, 소스를 보고, 콘텐츠를 교체하십시오. 파일 하단의 연결 코드는 약 60줄입니다.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

관련 스킬