GODRICH
#css애니메이션#버튼#로딩#전환효과#스크롤#대시보드#실전ui#디자인트렌드

css 로딩바 애니메이션 9가지 — 3D 계산형 로더

css 로딩바 애니메이션도 아홉 개 모두 트윈이 아니라 계산으로 돕니다. 로딩이 시작되는 첫 프레임에는 평평한 정면 한 장만 보이지만, 값이 문턱을 넘을 때마다 정육면체 면이 넘어가고 와이어프레임 정점이 제자리로 모여들며, 마지막 프레임에서는 안쪽 고리의 세차각이 가장 크게 벌어진

아홉 개 모두 perspective·transform-style: preserve-3d 위에서 render(p) 하나가 진행률 p(0~1)를 받아 좌표나 각도를 다시 계산합니다. 클릭·스페이스바(정지 토글)·R(재시작)·창 크기 조절 이벤트 네 가지를 그대로 공유하고, Math.random() 은 한 번도 부르지 않은 채 고정 상수와 삼각함수로만 움직임을 만듭니다.

자동 재생 · 눌러서 해당 항목으로 · 전부 한 zip

아홉 개는 값이 도형의 어느 부분을 바꾸는가로 나뉩니다. 01·06 은 값을 면 인덱스로 바꿔 큐브·다각기둥의 면을 하나씩 넘기고, 02·05·08 은 값을 좌표 보간 비율로 바꿔 정점·점·격자가 목표 위치로 모이거나 솟아오르며, 03·07 은 값을 깊이 순위로 바꿔 카드·패널을 화가 알고리즘으로 다시 정렬하고, 04·09 는 값을 각도로 바꿔 고리를 좁히거나 세차운동으로 벌립니다.

395 캔버스 rAF 로더·393 포인터 tilt 버튼과 이 아홉 개가 갈라지는 지점

395 의 아홉 로더는 <canvas> 2D 컨텍스트 위에서 굴절·물결 같은 픽셀 단위 계산을 직접 그려 넣는 rAF 물리 데모였고, 393 의 아홉 버튼은 포인터가 움직이는 좌표를 실시간으로 읽어 그 순간의 마우스 위치에 반응해 기울어집니다. 이 편은 그 둘과 다른 세 번째 축입니다 — 좌표를 직접 그리지도, 입력 이벤트에 반응해 기울지도 않고, CSS perspective·transform-style: preserve-3d 가 이미 그려 둔 3D 공간 위에 진행률 p 하나가 면 전환 문턱(01)·정점 lerp 곡선(02)·세차각(09) 같은 계산을 얹습니다.

css 로딩 애니메이션 치고는 입력에 반응하지 않는 대신, 클릭·스페이스바로 멈췄다가 다시 가도 같은 계산이 정확히 같은 프레임을 재현합니다. 화면에 보이는 회전은 브라우저의 트랜지션 보간이 아니라 매 프레임 render(p) 가 새로 정하는 좌표입니다.

01값이 문턱을 넘을 때마다 다음 면으로 넘어가는 정육면체 로더

진행률 pct 를 FACE_THRESHOLD(25) 로 나눈 몫만큼 정육면체를 90도씩 돌리고, 매 프레임 네 면의 법선각(NORMALS)과 현재 회전각의 코사인을 깊이로 삼아 화가 알고리즘으로 z-index 를 다시 매겨 backface-visibility: hidden 뒤판이 앞면을 가리지 않게 합니다. 파일 변환·설치 단계처럼 몇 단계로 딱 나뉘는 진행률에 씁니다.

값이 문턱을 넘을 때마다 다음 면으로 넘어가는 정육면체 로더
새 창에서 열기

01 · 값이 문턱을 넘을 때마다 다음 면으로 넘어가는 정육면체 로더 — 측정 누적면적 8.577% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

FACE_THRESHOLDNORMALSbackface-visibility
var FACE_THRESHOLD = 25; // 면 하나를 넘길 진행률 문턱(%) — 변형 01 대상
var t0 = 0, raf = 0, paused = false, lastP = 0;

// 화가 알고리즘 — 각 면의 (법선각 + 현재 회전각) 코사인을 깊이로 써서 뒤에서 앞 순서로 z-index 를 매긴다.
function depthSort(rotY) {
  var withDepth = faces.map(function (el, i) {
    return { el: el, depth: Math.cos((NORMALS[i] + rotY) * Math.PI / 180) };
  });
  withDepth.sort(function (a, b) { return a.depth - b.depth; });
  withDepth.forEach(function (o, idx) { o.el.style.zIndex = String(idx); });
}

function render(p) {
  lastP = p;
  var pct = Math.round(p * 100);
  var idx = Math.min(faces.length - 1, Math.floor(pct / FACE_THRESHOLD));
  var rotY = idx * 90;
  cube.style.transform = 'rotateY(' + rotY + 'deg)';
  depthSort(rotY);
  pctEl.textContent = pct + '%';
}

02진행률 값만큼 정점이 제자리로 모이는 와이어프레임 로더

여덟 정점을 흩어둔 SCATTER 좌표에서 정육면체 꼭짓점 TARGETS 까지 Math.pow(p, LERP_EASE_POW) 비율로 옮기고, 옮겨진 정점끼리 선을 이어 큐브 안에서 윤곽이 값이 오를수록 또렷해집니다. 3D 에셋·지도 데이터를 불러오는 화면에 어울립니다.

진행률 값만큼 정점이 제자리로 모이는 와이어프레임 로더
새 창에서 열기

02 · 진행률 값만큼 정점이 제자리로 모이는 와이어프레임 로더 — 측정 누적면적 4.867% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

LERP_EASE_POWTARGETStransform-style
function render(p) {
  lastP = p;
  var e = ease(p);
  var rotY = (p * 360 * ROT_TURNS) % 360;
  cube.style.transform = 'rotateX(18deg) rotateY(' + rotY + 'deg)';
  for (var i = 0; i < 8; i++) {
    var sx = SCATTER[i][0], sy = SCATTER[i][1], sz = SCATTER[i][2];
    var tx = TARGETS[i][0], ty = TARGETS[i][1], tz = TARGETS[i][2];
    var cx = sx + (tx - sx) * e;
    var cy = sy + (ty - sy) * e;
    var cz = sz + (tz - sz) * e;
    vtx[i].style.transform = 'translate3d(' + cx + 'px,' + cy + 'px,' + cz + 'px)';
    vtx[i].style.opacity = String(0.25 + 0.75 * e);
  }
  updateLines(e);
  pctEl.textContent = Math.round(p * 100) + '%';
}

03값이 오를 때마다 뒤 카드가 깊이 순서를 바꿔 앞으로 넘어오는 카드 스택 로더

카드마다 진행률 p×5 에서 구한 깊이 순위로 ZGAP(22px)만큼 뒤로, SHRINK(9%)만큼 작게, OPACITY_STEP(15%)만큼 흐리게 배치해 맨 뒤 카드가 매 단계 맨 앞으로 넘어오는 순환을 만듭니다. 다단계 결제·온보딩 단계 표시에 씁니다.

값이 오를 때마다 뒤 카드가 깊이 순서를 바꿔 앞으로 넘어오는 카드 스택 로더
새 창에서 열기

03 · 값이 오를 때마다 뒤 카드가 깊이 순서를 바꿔 앞으로 넘어오는 카드 스택 로더 — 측정 누적면적 5.401% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

ZGAPSHRINKOPACITY_STEP
// 카드 i 의 현재 깊이 순위(0=맨 앞)를 진행률의 연속 모듈러 함수로 계산 — 상태를 누적하지 않고
// 매 프레임 p 하나로부터 전체 순서를 다시 구한다(화가 알고리즘과 같은 원리).
function rankOf(i, s) {
  var r = (i - s) % CARD_COUNT;
  if (r < 0) r += CARD_COUNT;
  return r;
}

function render(p) {
  lastP = p;
  var s = p * CARD_COUNT;
  for (var i = 0; i < CARD_COUNT; i++) {
    var rank = rankOf(i, s);
    var z = -rank * ZGAP;
    var y = rank * YOFF;
    var scale = 1 - rank * SHRINK;
    var op = 1 - rank * OPACITY_STEP;
    cards[i].style.transform = 'translateY(' + y + 'px) translateZ(' + z + 'px) scale(' + scale + ')';
    cards[i].style.opacity = String(Math.max(0.25, op));
    cards[i].style.zIndex = String(Math.round((CARD_COUNT - rank) * 1000));
  }
  pctEl.textContent = Math.round(p * 100) + '%';
}

04값이 오를수록 고리 사이 기울기 차이가 좁혀지는 궤도 로더

고리 네 개를 72·54·36·18도로 다르게 기울여 두고 INITIAL_TILT[i] * (1-p) 로 정면(0도) 쪽으로 좁히면서 SPIN_TURNS(0.6바퀴)만큼 같이 돌려, 값이 다 차면 네 고리가 한 각도로 겹칩니다. 동기화 진행·다중 계층 로딩에 씁니다.

값이 오를수록 고리 사이 기울기 차이가 좁혀지는 궤도 로더
새 창에서 열기

04 · 값이 오를수록 고리 사이 기울기 차이가 좁혀지는 궤도 로더 — 측정 누적면적 15.808% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

INITIAL_TILTSPIN_TURNSperspective
var INITIAL_TILT = [72, 54, 36, 18]; // 고리마다 다른 시작 기울기(deg) — 값이 오를수록 0 으로 수렴
var SPIN_TURNS = 0.6;                 // 한 루프 동안 고리 묶음이 도는 회전수

var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var LOOP = 2;
var REDUCE_P = 0.7;
var t0 = 0, raf = 0, paused = false, lastP = 0;

function render(p) {
  lastP = p;
  var spinY = (p * 360 * SPIN_TURNS) % 360;
  for (var i = 0; i < rings.length; i++) {
    var tilt = INITIAL_TILT[i] * (1 - p); // 정면 각도(0deg) 쪽으로 진행률 비례 보간
    rings[i].style.transform = 'rotateY(' + spinY + 'deg) rotateX(' + tilt + 'deg)';
  }
  pctEl.textContent = Math.round(p * 100) + '%';
}

05구 표면의 점들이 한 점으로 모이는 수렴 로더

황금각(GOLDEN_ANGLE)으로 구 표면에 고르게 흩은 점 28개를 SPHERE_R(78px) 반지름에서 중심까지 1-p 배율로 당겨 한 점으로 수렴시킵니다. 데이터 동기화 완료·앱 초기화 화면에 씁니다.

구 표면의 점들이 한 점으로 모이는 수렴 로더
새 창에서 열기

05 · 구 표면의 점들이 한 점으로 모이는 수렴 로더 — 측정 누적면적 6.127% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

GOLDEN_ANGLESPHERE_Rtransform-style
var POINT_COUNT = 28;
var SPHERE_R = 78;
var GOLDEN_ANGLE = Math.PI * (3 - Math.sqrt(5)); // 피보나치 구 분포 각(고정 상수, 무작위 없음)
var ROT_TURNS = 0.5;

// 피보나치 구 분포 — 점 i 의 구면 좌표를 결정적으로 계산한다.
var BASE = [];
for (var i = 0; i < POINT_COUNT; i++) {
  var y = 1 - (i / (POINT_COUNT - 1)) * 2;
  var r = Math.sqrt(Math.max(0, 1 - y * y));
  var theta = GOLDEN_ANGLE * i;
  BASE.push([Math.cos(theta) * r * SPHERE_R, y * SPHERE_R, Math.sin(theta) * r * SPHERE_R]);
}

06회전하며 넘는 면부터 색이 채워지는 다각기둥 로더

육각기둥(PRISM_SIDES=6)을 계속 회전시키며 면 i 의 문턱 i / PRISM_SIDES 를 넘은 뒤 FILL_SPAN 폭 동안 선형으로 불투명도를 채워, 회전할 때마다 채워진 경계가 눈에 보입니다. 설문 진행·재고 채우기 표시에 씁니다.

회전하며 넘는 면부터 색이 채워지는 다각기둥 로더
새 창에서 열기

06 · 회전하며 넘는 면부터 색이 채워지는 다각기둥 로더 — 측정 누적면적 16.692% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

PRISM_SIDESFILL_SPANtransform-style
// 면 i 의 문턱은 i / PRISM_SIDES — 진행률이 그 문턱을 넘으면 FILL_SPAN 동안 선형으로 번져 채워지고,
// 그 뒤로는 값이 줄지 않는 한(루프가 돌아 p 가 다시 작아지기 전까지) 채워진 채로 유지된다.
function fillAmount(i, p) {
  var threshold = i / PRISM_SIDES;
  var raw = (p - threshold) / FILL_SPAN;
  if (raw < 0) return 0;
  if (raw > 1) return 1;
  return raw;
}

function render(p) {
  lastP = p;
  var rotY = (p * 360 * ROT_TURNS) % 360;
  prism.style.transform = 'rotateX(-14deg) rotateY(' + rotY + 'deg)';
  for (var i = 0; i < PRISM_SIDES; i++) {
    fills[i].style.opacity = String(fillAmount(i, p));
  }
  pctEl.textContent = Math.round(p * 100) + '%';
}

07패널이 뒤집힐 때마다 앞뒤 순서를 다시 계산하는 플립 로더

패널 다섯 장을 STEP(1/5) 구간마다 하나씩 0→180도로 뒤집으면서, 그 순간 지금 뒤집는 패널까지의 거리로 전 패널의 깊이(RANK_ZGAP)를 다시 정렬해 뒷면이 늘 자연스럽게 겹칩니다. css 카드 뒤집기 애니메이션을 튜토리얼 단계 넘기기·카드형 안내 진행에 붙이기 좋습니다.

패널이 뒤집힐 때마다 앞뒤 순서를 다시 계산하는 플립 로더
새 창에서 열기

07 · 패널이 뒤집힐 때마다 앞뒤 순서를 다시 계산하는 플립 로더 — 측정 누적면적 12.239% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

RANK_ZGAPSTEPbackface-visibility
// 패널 i 의 회전 각도 — 자기 구간 안에서만 0→180도로 선형 보간, 구간 전은 0, 구간 후는 180 고정.
function flipAngle(i, p) {
  var start = i * STEP, end = start + STEP;
  if (p < start) return 0;
  if (p >= end) return 180;
  var local = (p - start) / STEP;
  return local * 180;
}
// 패널 i 의 깊이 순위 — "지금 뒤집는 패널까지의 거리". 거리가 멀수록 뒤로 밀린다.
function depthRank(i, p) {
  var cur = currentIndex(p);
  return Math.abs(cur - i);
}

function render(p) {
  lastP = p;
  for (var i = 0; i < PANEL_COUNT; i++) {
    var angle = flipAngle(i, p);
    var rank = depthRank(i, p);
    panels[i].style.transform = 'translateZ(' + (-rank * RANK_ZGAP) + 'px) translateY(' + (rank * RANK_YOFF) + 'px) rotateY(' + angle + 'deg)';
    panels[i].style.zIndex = String(PANEL_COUNT - rank);
  }
  pctEl.textContent = Math.round(p * 100) + '%';
}

08격자점이 값만큼 솟아 지형처럼 보이는 원근 로더

가로 GRID_COLS(7)×세로 5 격자점마다 두 사인·코사인 물결을 겹쳐 고정 높이 값을 미리 정해 두고, 진행률 p 만큼 HEIGHT_SCALE(54px)로 끌어올리며 TILT(58도)로 눕혀 원근감을 냅니다. 지도 데이터 불러오기·대시보드 초기 로딩 배경에 씁니다.

격자점이 값만큼 솟아 지형처럼 보이는 원근 로더
새 창에서 열기

08 · 격자점이 값만큼 솟아 지형처럼 보이는 원근 로더 — 측정 누적면적 7.95% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

GRID_COLSHEIGHT_SCALETILT
function render(p) {
  lastP = p;
  var rotY = (p * 360 * ROT_TURNS) % 360;
  grid.style.transform = 'rotateX(' + TILT + 'deg) rotateZ(' + rotY + 'deg)';
  for (var i = 0; i < pts.length; i++) {
    var b = base[i];
    var rise = b[2] * p * HEIGHT_SCALE;
    pts[i].style.transform = 'translate3d(' + b[0] + 'px,' + (-rise) + 'px,' + b[1] + 'px)';
  }
  pctEl.textContent = Math.round(p * 100) + '%';
}

09값이 오를수록 안쪽 고리의 세차각이 벌어지는 자이로스코프 로더

안쪽 고리의 회전축이 그리는 원뿔 위상(PRECESSION_TURNS=1.5바퀴)의 cos·sin 을 X·Z 축에 나눠 실어, PRECESSION_FACTOR(26)×p 만큼 벌어지는 세차각이 OUTER_TILT(22도) 바깥 고리와의 차이로 눈에 보이는 흔들림을 만듭니다. 장기 대기 로딩·백그라운드 동기화 표시에 씁니다.

값이 오를수록 안쪽 고리의 세차각이 벌어지는 자이로스코프 로더
새 창에서 열기

09 · 값이 오를수록 안쪽 고리의 세차각이 벌어지는 자이로스코프 로더 — 측정 누적면적 7.29% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

PRECESSION_FACTORPRECESSION_TURNSOUTER_TILT
// 안쪽 고리의 회전축이 그리는 원뿔 — 세차각(진행률에 비례해 커진다)을 원뿔 위상의 cos/sin 으로
// X축·Z축 두 방향에 나눠 실어, 축 자체가 원을 그리며 벌어지는 세차운동을 흉내 낸다.
function render(p) {
  lastP = p;
  var spinY = (p * 360 * SPIN_TURNS) % 360;
  var maxAngle = PRECESSION_FACTOR * p;
  var conePhase = (p * 360 * PRECESSION_TURNS) % 360;
  var rad = conePhase * Math.PI / 180;
  var tiltX = OUTER_TILT + maxAngle * Math.cos(rad);
  var tiltZ = maxAngle * Math.sin(rad);
  outer.style.transform = 'rotateY(' + spinY + 'deg) rotateX(' + OUTER_TILT + 'deg)';
  inner.style.transform = 'rotateY(' + spinY + 'deg) rotateX(' + tiltX + 'deg) rotateZ(' + tiltZ + 'deg)';
  pctEl.textContent = Math.round(p * 100) + '%';
}

면·정점·깊이 값이 한 루프 동안 화면을 얼마나 바꾸는지 — 아홉 항목 실측

항목 누적면적 강도_평균 움직인프레임
01 정육면체 면 전환 8.6% 92.8 23/23
02 와이어프레임 정점 스냅 4.9% 87.1 23/23
03 카드 스택 깊이 순환 5.4% 95.2 23/23
04 고리 궤도 기울기 15.8% 102.8 23/23
05 구면 점 수렴 6.1% 150.6 23/23
06 다각기둥 면 채움 16.7% 142.6 23/23
07 플립 패널 깊이 정렬 12.2% 217.6 23/23
08 격자 지형 상승 8.0% 141.8 23/23
09 자이로 세차 7.3% 88.9 23/23

아홉 개 모두 23/23 프레임이 움직여 멈춰 있는 순간이 없습니다. 누적면적은 06(16.7%)·04(15.8%)가 가장 넓은데 육각기둥 여섯 면 전체와 고리 네 개가 화면을 크게 덮기 때문이고, 02(4.9%)가 가장 좁은 건 가는 선 12개짜리 와이어프레임이라 로더 요소 자체가 작아서입니다 — 컴포넌트 급 로더는 원래 면적이 작은 게 정상이고, 그 대신 화가 알고리즘·lerp 곡선 같은 계산 한 겹으로 품질을 잽니다. 강도는 07(217.6)이 가장 세게 튀는데, 패널이 뒤집히는 순간 대비가 큰 두 면이 한 프레임에 같이 움직이기 때문입니다.

대시보드 스켈레톤 대신 이 css 로딩 애니메이션 아홉 개를 어디에 붙이나?

검색·파일 업로드처럼 몇 초 안에 끝나는 로딩엔 01 정육면체 면 전환이나 03 카드 스택처럼 단계가 딱 떨어지는 쪽이 자연스럽습니다. 서버가 진짜 진행률 값을 안 줘도, 문턱 네 개(01)나 카드 다섯 장(03)이 순서대로 넘어가는 모습만으로 사용자는 뭔가 진행되고 있다는 걸 읽습니다.

반대로 지도 타일·3D 에셋처럼 실제로 몇 초씩 걸리는 로딩엔 08 격자 지형처럼 값이 오를수록 점점 솟아오르는 쪽이 진행률 없는 스피너보다 이탈을 줄입니다. 온보딩 튜토리얼의 단계 넘기기에는 07 플립 패널을 진행 표시 겸 스텝 인디케이터로 같이 씁니다.

FACE_THRESHOLD·PRECESSION_FACTOR 값이 1.0 에 끝내 닿지 못해 깨지는 지점

t0 = performance.now() 뒤 p = (t % LOOP) / LOOP 는 연속된 값이라, t 가 LOOP(2초)의 배수에 닿는 찰나 p 는 1 이 아니라 그대로 다음 루프의 0 으로 넘어갑니다. 04 는 tilt = INITIAL_TILT[i] * (1 - p) 로 고리 기울기를 0도에 접근시키지만 p 가 정확히 1 에 닿는 프레임이 없어, 네 고리는 매 루프 끝에서 0.0x도의 미세한 기울기 차이를 남긴 채 다시 벌어집니다. 09 도 같은 이유로 maxAngle = PRECESSION_FACTOR * p 가 26에 끝내 닿지 못하고 25점대에서 리셋되어, 배지 숫자가 100% 를 스치듯 지나갈 뿐 정확히 찍지는 않습니다. 소스를 내려받아 이 지점을 직접 고쳐 보려는 분은 gfc9k6p7 을 입력해 압축을 풀면 아홉 개 원본을 한 번에 받을 수 있습니다.

reduced-motion 설정 하나로 아홉 개가 동시에 멈추는 이유 — 접근성

prefers-reduced-motion 이 reduce 이면 raf 루프 자체를 돌리지 않고 render(REDUCE_P)(0.7)로 고정 프레임 한 장만 그립니다. 클릭·스페이스바·R 키는 여전히 동작하지만 reduce 상태에서는 togglePause·restart 가 다시 render(REDUCE_P)만 호출해 화면은 항상 같은 자세로 돌아옵니다 — 로더가 멎어 있다는 오해를 막으려 0%·100% 양 끝이 아니라 70% 지점 한 장으로 고정한 선택입니다. role="application"·aria-label 은 스크린리더가 각 로더를 무슨 실험판인지 읽게 해 줍니다.

FACE_THRESHOLD·LERP_EASE_POW·PRECESSION_FACTOR 세 값만 바꿔도 css 3d 회전 인상이 달라진다

이름 바꾼 값 느낌
정육면체 면 전환 문턱 조정 01 FACE_THRESHOLD 25 → 18 문턱 값을 낮추면 더 적은 진행률 값으로도 다음 면으로 넘어가 면 전환이 더 잦아지는 쪽에 가깝습니다
와이어프레임 정점 lerp 속도 조정 02 LERP_EASE_POW 1.8 → 1.2 보간 속도 지수를 낮추면 정점이 목표 좌표에 더 빨리 도착해 도형 윤곽이 이른 진행률에서 먼저 또렷해지는 쪽에 가깝습니다 — 지수가 클수록 시작이 느린 곡선이라 낮출수록 초반 이동이 빨라집니다
자이로스코프 세차각 계수 조정 09 PRECESSION_FACTOR 26 → 34 계수를 높이면 같은 진행률에서도 안쪽 고리 세차각이 더 크게 벌어져 흔들림이 더 두드러지는 쪽에 가깝습니다

정육면체 말고 다른 3D 회전·틸트 로더는 어디서 보나?

포인터를 따라 기울어지는 카드·버튼이 궁금하면 css 버튼 입체감 9가지 — 클릭 효과까지 커스텀 코드 를, 캐러셀처럼 옆으로 넘기는 큐브가 필요하면 CSS 3D 큐브 캐러셀 틸트 9종 — 한 줄 복붙으로 를, 마우스를 따라 통째로 도는 장면이 필요하면 마우스를 따라오는 CSS 3D 회전 장면 9종 을 엽니다. rAF 물리 계산으로 그리는 캔버스 쪽 로더 아홉 개는 캔버스 로딩 애니메이션 효과 9가지 — 코드 그대로 에 있습니다.

3D 로더 zip 을 열기 전에 자주 나오는 질문

css 카드 뒤집기 애니메이션(07)만 따로 떼어 써도 되나요?

네, 07 은 PANEL_COUNT·STEP·RANK_ZGAP 세 값과 flipAngle·depthRank 두 함수만 있으면 다른 로더 없이도 그대로 동작합니다. HTML 구조(패널 다섯 장)와 CSS perspective·preserve-3d만 같이 가져가면 됩니다.

9개 중 성능이 가장 무거운 건 무엇인가요?

강도_평균 기준으로는 07(217.6)이 가장 세게 움직이는데, 패널이 뒤집히는 순간 두 면이 동시에 대비 크게 바뀌기 때문입니다. DOM 요소 개수로 보면 02 가 정점 8개·선 12개를 매 프레임 좌표 계산으로 다시 그려 가장 무겁습니다.

아홉 로더 중 하나만 프로젝트에 붙이고 나머지 여덟은 빼도 문제없나요?

네, 아홉 개는 서로 참조하지 않는 독립된 IIFE 라 로더 블록 하나와 그 항목의 스크립트만 옮기면 됩니다. 다만 demo-tokens.scss 팔레트 변수는 아홉 개가 공유하므로 색을 그대로 쓰려면 같이 가져갑니다.

압축 비밀번호를 입력하세요

비밀번호는 이 글 본문 안에 있습니다. 읽다 보면 나옵니다.