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

귀여운 캐릭터 애니메이션 9종 — 일러스트 캐릭터 CSS 모음

귀여운 캐릭터 애니메이션은 그린 캐릭터를 이미지 파일 없이 코드만으로 깜빡이고 튀게 만드는 일입니다. 하트 눈 얼굴에서 쿠키 나눠 주는 친구까지 아홉 마리를 CSS 와 SVG 도형으로 지었고, 클릭하면 캐릭터가 바로 반응한다는 규칙 하나로 움직입니다.

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

순서는 난이도순도 인기순도 아니고, 캐릭터가 관객과 가까워지는 순서입니다. 먼저 혼자 표정을 짓고(01~03), 스스로 등장하고 걷고(04~05), 서로 말을 주고받고(06), 사람을 기다렸다 반응하고(07~08), 마지막에는 사람과 쿠키를 나눕니다(09). 아홉 마리 전부 뼈대는 원·알약·반달 같은 도형 몇 개라서, 그려 넣은 귀여운 일러스트 캐릭터를 코드로 옮기는 셈입니다. 사람 형태 캐릭터의 관절·걸음을 더 보려면 마스코트 애니메이션이, 배경까지 통째로 장면을 꾸미려면 CSS 장면 그리기가 이어지고, 하트 파티클을 더 쏟고 싶으면 파티클 효과로 건너가면 됩니다.

01하트 눈 깜빡임

두 눈이 하트로 차 있는 동그란 얼굴이 몇 초에 한 번 눈을 감는, 로그인 완료 인사 화면에 둘 캐릭터입니다.

하트 눈 깜빡임
새 창에서 열기

01 · 하트 눈 깜빡임 — 측정 누적면적 2.374% · 움직인 프레임 11/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

transform-originscaleYanimation-iteration-count

깜빡임은 눈을 세로로 눌러 그린다

.hb.is-demo .hb__eye {
  animation-name: hbBlink;
  animation-duration: $duration;
  animation-timing-function: $easing;
  animation-iteration-count: infinite;
}
@keyframes hbBlink {
  0%, 40% { transform: scaleY(1); }
  47% { transform: scaleY(.08); }
  54%, 100% { transform: scaleY(1); }
}

눈꺼풀 오버레이를 얹으면 두 겹이 겹쳐 유령처럼 보이므로 눈 요소 하나를 scaleY(.08) 로 세로로 눌렀고, 깜빡임은 2초 루프의 47% 앞뒤 짧은 순간에만 일어납니다.

하트 박동과 뺨이 빈 구간을 메운다

@keyframes hbBeat {
  0%, 12% { transform: scale(1); }
  17% { transform: scale(1.14); }
  22% { transform: scale(1); }
  27% { transform: scale(1.1); }
  32%, 100% { transform: scale(1); }
}
@keyframes hbBlush {
  0%, 61% { opacity: 0; }
  62%, 87% { opacity: .55; }
  88%, 100% { opacity: 0; }
}

깜빡임 사이의 긴 정지를 박동 두 번과 뺨 발그레가 채워 움직인 프레임이 11/23 · 누적면적이 2.374% 로 측정됐고, 실제로 누르면 aria-pressed 로 뺨이 0.55 · 하트가 1.16 배로 같은 모습이 정적으로 남습니다.

02폭신 젤리 튀어오름

젤리가 웅크렸다 세로로 늘며 뛰고 착지에서 좌우로 출렁이는, 게임 시작 버튼 옆에 둘 마스코트입니다.

폭신 젤리 튀어오름
새 창에서 열기

02 · 폭신 젤리 튀어오름 — 측정 누적면적 12.578% · 움직인 프레임 17/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

cubic-bezierscaletranslateY

스쿼시와 스트레치를 transform 하나로

@keyframes jlHop {
  0% { transform: translateX(-50%) scale(1, 1); }
  8% { transform: translateX(-50%) scale(1.16, .66); }
  16% { transform: translateX(-50%) translateY(-52px) scale(.9, 1.16); }
  24% { transform: translateX(-50%) translateY(-18px) scale(.98, 1.05); }
  30% { transform: translateX(-50%) scale(1.12, .78); }
  38% { transform: translateX(-50%) scale(.96, 1.06); }
  46% { transform: translateX(-50%) scale(1.06, .93); }
  54% { transform: translateX(-50%) scale(.97, 1.04); }
  62% { transform: translateX(-50%) scale(1.03, .97); }
  70%, 100% { transform: translateX(-50%) scale(1, 1); }
}

납작해지고 늘어나는 모양을 전부 scale 로 표현해 width·height 를 건드리지 않으므로 매 프레임 레이아웃이 다시 돌지 않고, 착지 뒤 출렁임이 네 번 감쇠하며 17/23 프레임을 움직입니다.

누를 때마다 한 번 더 크게 튄다

document.querySelector('.jl__hit').addEventListener('click', function () {
  jl.classList.remove('is-demo');
  hits = hits + 1;
  count.textContent = String(hits);
  body.classList.remove('jl__body--boing');
  void body.offsetWidth;
  body.classList.add('jl__body--boing');
});

같은 요소에 애니메이션 클래스가 붙어 있으면 재시작하지 않으므로, 지웠다가 void body.offsetWidth 로 강제로 한 번 읽어 다시 끼우면 높이 뜨는 일회성 바운스가 처음부터 재생됩니다.

03배 흔들기 웃음

반달 눈으로 웃으며 몸이 기울고 배가 출렁이는, 댓글 남기기 성공 배지에 어울리는 캐릭터입니다.

배 흔들기 웃음
새 창에서 열기

03 · 배 흔들기 웃음 — 측정 누적면적 8.074% · 움직인 프레임 22/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

rotatescaleXanimation-duration

기울기의 원점은 발바닥에 둔다

.bn__bean {
  --tilt: 4deg;
  position: absolute; bottom: 4px; left: 50%; width: 52%; aspect-ratio: 1 / 1.18;
  background: $color; border: 3px solid $subject-ink;
  border-radius: 50% 50% 46% 46% / 42% 42% 58% 58%;
  transform: translateX(-50%);
  transform-origin: 50% 100%; // 붙는 지점: 발바닥 — 몸이 기울어도 발은 제자리
}

원점을 몸 중심에 두면 기울어질 때 발이 바닥에서 미끄러져 떠 보이는데, 50% 100% 발바닥 원점으로 두니 몸이 아무리 기울어도 발은 제자리에 붙어 있습니다.

웃음 단계는 변수 하나가 곧 진폭

.bn[data-level="1"] .bn__bean { --tilt: 8deg; }
.bn[data-level="2"] .bn__bean { --tilt: 13deg; }
.bn[data-level="3"] .bn__bean {
  --tilt: 4deg;
  animation: bnFold 700ms cubic-bezier(.2, 1.4, .4, 1) 1 forwards;
}
@keyframes bnTilt {
  0%, 100% { transform: translateX(-50%) rotate(calc(var(--tilt) * -1)); }
  50% { transform: translateX(-50%) rotate(var(--tilt)); }
}

누를 때마다 data-level 이 오르고 --tilt 값만 바뀌어 좌우 기울기가 커지다가, 3단계에서는 몸이 앞으로 접히는 애니메이션이 한 번 돌며 22/23 프레임을 움직입니다.

04낙서 선 캐릭터 걷기

얇은 선으로 그린 캐릭터가 자기 선을 그려가며 화면 밖에서 걸어 들어오는, 소개 페이지 스크롤 안내 캐릭터입니다.

낙서 선 캐릭터 걷기
새 창에서 열기

04 · 낙서 선 캐릭터 걷기 — 측정 누적면적 12.113% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

stroke-dashoffsetstroke-linecaptranslateX

등장은 선이 스스로 그려지는 것

.dw__draw {
  fill: none; stroke: $subject-ink; stroke-width: 4;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 100; stroke-dashoffset: 0;
}
@keyframes dwDraw {
  0% { stroke-dashoffset: 100; }
  38%, 100% { stroke-dashoffset: 0; }
}

모든 path 에 pathLength="100" 을 걸어 실제 길이와 무관하게 100 으로 통일했기에 stroke-dashoffset 값 하나로 몸·다리·팔이 같은 속도로 그려지고, 그리기는 2초의 첫 38% 에 끝납니다.

다리와 팔은 붙는 지점을 축으로 교대로 돈다

// 다리·팔 — 엉덩이·어깨(붙는 지점)를 원점으로 교대로 흔든다.
// SVG 자식의 transform-origin 은 transform-box: view-box 를 명시해야 viewBox 좌표(px) 로 잡힌다
.dw__leg { transform-box: view-box; transform-origin: 200px 148px; }
.dw__arm { transform-box: view-box; transform-origin: 200px 104px; }
.dw__leg--l, .dw__arm--r { animation-name: dwSwingA; }
.dw__leg--r, .dw__arm--l { animation-name: dwSwingB; }
.dw__leg, .dw__arm {
  animation-duration: .5s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}
@keyframes dwSwingA {
  0%, 100% { transform: rotate(16deg); }
  50% { transform: rotate(-16deg); }
}
@keyframes dwSwingB {
  0%, 100% { transform: rotate(-16deg); }
  50% { transform: rotate(16deg); }
}

왼다리와 오른팔이 같은 키프레임을, 오른다리와 왼팔이 반대 키프레임을 돌아 걸음이 되고, 방향 바꾸기 단추를 누르면 안쪽 층만 scaleX(-1) 로 뒤집혀 반대로 걷습니다.

05스티커 팝 등장

하얀 테두리를 두른 스티커가 없다가 튀어나와 살짝 과하게 커졌다 앉는, 프로필 꾸미기 스티커 판용 부품입니다.

스티커 팝 등장
새 창에서 열기

05 · 스티커 팝 등장 — 측정 누적면적 27.173% · 움직인 프레임 14/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

transform-origincubic-bezierbox-shadow

0 에서 튀어나와 과잉했다가 앉는다

@keyframes stPop {
  0% { transform: rotate(-10deg) scale(0); }
  14% { transform: rotate(0deg) scale(1.16); }
  24% { transform: rotate(-4deg) scale(.96); }
  32%, 58% { transform: rotate(-4deg) scale(1); }
  64% { transform: rotate(-4deg) scale(1.05); }
  72%, 100% { transform: rotate(-4deg) scale(1); }
}

14% 지점에서 실제 크기의 1.16 배까지 지나쳤다가 0.96 으로 살짝 처지는 오버슛이 착 붙는 느낌을 만들고, 등장부터 윙크까지 쉬는 구간이 짧아 누적면적 27.173% 를 기록했습니다.

표정 교체는 한 프레임 컷으로

.st__eyeWink { border-top: 4px solid $subject-ink; border-radius: 50%; visibility: hidden; }
.st__eyeWink--l { left: 26%; }
.st__eyeWink--r { right: 26%; }
.st--wink .st__eyeOpen--r { visibility: hidden; }
.st--wink .st__eyeWink--r { visibility: visible; }
sticker.classList.toggle('st--wink', hits % 5 === 0 && hits > 0);
sticker.classList.remove('st--nudge');
void sticker.offsetWidth;
sticker.classList.add('st--nudge');

열린 눈과 윙크 눈 두 벌을 같은 칸에 겹쳐 두고 보이는 쪽을 visibility 로 골라 다섯 번째 누름에 표정이 한 번에 바뀌며, 페이드로 옮기면 두 표정이 반투명하게 겹쳐 한 장에 남습니다.

06말풍선 대화 번갈아

마주 본 두 캐릭터가 말풍선을 주고받는, 고객센터 채팅 첫 인사에 놓을 짝입니다.

말풍선 대화 번갈아
새 창에서 열기

06 · 말풍선 대화 번갈아 — 측정 누적면적 27.268% · 움직인 프레임 16/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

scaleYscaleanimation-delay

꼬리가 먼저 나오고 몸이 펴진다

.ch.is-demo .ch__tail { animation-name: chTail; animation-duration: $duration; animation-delay: -60ms; animation-timing-function: $easing; animation-iteration-count: infinite; }
@keyframes chPopL {
  0% { transform: scale(0); }
  10% { transform: scale(1.08); }
  16%, 44% { transform: scale(1); }
  45%, 100% { transform: scale(0); }
}

꼬리 키프레임에 음수 animation-delay: -60ms 를 걸어 같은 2초 루프를 몸보다 한 발 먼저 돌게 했고, 풍선의 transform-origin 을 꼬리가 닿는 아래 귀퉁이에 두어 거기서부터 뻗어 펴집니다.

누르면 내 말풍선이 고정된다

.ch.mine .ch__bubble--l { animation: none; transform: scale(1); }
.ch.mine .ch__bubble--r { animation: none; transform: scale(0); }
document.querySelector('.ch__hit').addEventListener('click', function () {
  ch.classList.remove('is-demo');
  var on = ch.classList.toggle('mine');
  this.setAttribute('aria-pressed', String(on));
});

누르는 순간 미리보기 루프를 끄고 .mine 클래스로 왼쪽 풍선만 펴서 고정하며, 상태는 aria-pressed 한 곳에만 실리며, 움직인 프레임은 16/23 · 누적면적은 27.268% 로 나왔습니다.

07꼬리 흔드는 강아지 대기

자리를 지키며 꼬리를 흔들고 귀가 살랑거리는, 업로드 기다림 화면의 친구입니다.

꼬리 흔드는 강아지 대기
새 창에서 열기

07 · 꼬리 흔드는 강아지 대기 — 측정 누적면적 4.646% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

rotatetransform-originanimation-timing-function

꼬리·귀·고개는 저마다 붙는 지점이 축이다

.dg__tail {
  position: absolute; bottom: 38%; right: 16%; width: 6%; height: 24%;
  background: $subject-pink; border: 3px solid $subject-ink; border-radius: $r-pill;
  transform-origin: 50% 100%;
  animation-name: dgWag;
  animation-duration: .5s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}
@keyframes dgWag {
  0%, 100% { transform: rotate(-22deg); }
  50% { transform: rotate(22deg); }
}

꼬리 축은 몸에 닿은 아래 뿌리, 귀 축은 붙은 위쪽, 고개 축은 목이라 셋이 각자 흔들리는데 이 셋이 2초 내내 이어져 움직인 프레임이 23/23 으로 꽉 찼습니다.

쓰다듬을수록 꼬리가 빨라진다

.dg[data-speed="2"] .dg__tail { animation-duration: .36s; }
.dg[data-speed="3"] .dg__tail { animation-duration: .26s; }
pets = pets + 1;
dg.dataset.speed = String(Math.min(1 + Math.floor(pets / 3), 3));
dg.classList.toggle('dg--love', pets === 5);

세 번씩 쓰다듬을 때마다 꼬리 주기가 0.5s 에서 0.36s · 0.26s 로 짧아지고, 다섯 번째에는 눈이 반달로 컷 교체되며 하트가 머리 위로 한 번 떠오릅니다.

08반짝 눈 하트 파티클

눈 속에서 별이 도는 캐릭터 주위로 하트가 피어오르는, 좋아요 누르는 반응 화면용 캐릭터입니다.

반짝 눈 하트 파티클
새 창에서 열기

08 · 반짝 눈 하트 파티클 — 측정 누적면적 4.313% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

translateYscaleanimation-fill-mode

미리보기 하트 셋은 시차를 두고 피어오른다

.sp__auto {
  animation-name: spRise;
  animation-duration: $duration;
  animation-timing-function: $easing;
  animation-iteration-count: infinite;
  animation-fill-mode: backwards;
}
.sp__auto--1 { left: 30%; bottom: 34%; animation-delay: 0s; }
.sp__auto--2 { left: 56%; bottom: 30%; animation-delay: .66s; }
.sp__auto--3 { left: 42%; bottom: 44%; animation-delay: 1.32s; }

animation-fill-mode: backwards 로 지연 대기 구간에 미리 나타나지 않게 막았고, 0.66s 간격의 하트 세 개가 2초를 빈틈없이 채워 움직인 프레임이 23/23 입니다.

하트는 누른 자리에서 피어오른다

var rect = scene.getBoundingClientRect();
var heart = document.createElement('span');
heart.className = 'sp__fly';
heart.setAttribute('aria-hidden', 'true');
heart.innerHTML = HEART_SVG;
heart.style.left = ((e.clientX || rect.left + rect.width / 2) - rect.left) + 'px';
heart.style.top = ((e.clientY || rect.top + rect.height / 2) - rect.top) + 'px';
scene.appendChild(heart);
heart.addEventListener('animationend', function () { heart.remove(); });

누른 점의 화면 좌표를 장면 기준으로 환산해 그 자리에 하트를 심고 animationend 에 치우며, 하트는 커졌다가 크기가 0 으로 줄며 사라져 반투명 잔상이 남지 않습니다.

09쿠키 한 입씩 나눠 먹기

누를 때마다 쿠키가 네 단계로 줄고 볼이 부풀다가 다 먹으면 아쉬워하는, 하루 네 번 체크인 화면용 캐릭터입니다.

쿠키 한 입씩 나눠 먹기
새 창에서 열기

09 · 쿠키 한 입씩 나눠 먹기 — 측정 누적면적 11.737% · 움직인 프레임 8/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

clip-pathscaletranslateY

한 입은 원을 잘라 내는 것

.ck__cookie {
  position: absolute; inset: 0;
  background: $subject-cream; border: 5px solid $subject-orange-deep; border-radius: 50%;
  clip-path: circle(50% at 50% 50%);
}
.ck[data-bite="1"] .ck__cookie { clip-path: circle(44% at 60% 38%); }
.ck[data-bite="2"] .ck__cookie { clip-path: circle(36% at 66% 44%); }
.ck[data-bite="3"] .ck__cookie { clip-path: circle(26% at 70% 52%); }
.ck[data-bite="4"] .ck__cookie { clip-path: circle(15% at 72% 58%); }

clip-path: circle() 의 반지름과 중심을 단계마다 우측 상단으로 밀수록 왼쪽 아래 초승달만 남아 물린 자국으로 읽히고, 미리보기에서는 steps(1, end) 로 통째에서 세 입까지 20% 간격으로 컷이 넘어갑니다.

볼은 한 입마다 변수 하나로 부풀고

.ck__cheek {
  position: absolute; top: 46%; width: 22%; aspect-ratio: 1;
  background: $subject-pink; border-radius: 50%; opacity: .75;
  transform: scale(calc(1 + var(--puff)));
  transform-origin: 50% 50%;
}
.ck[data-bite="1"] .ck__char { --puff: .05; }
.ck[data-bite="2"] .ck__char { --puff: .1; }
.ck[data-bite="3"] .ck__char, .ck[data-bite="4"] .ck__char { --puff: .16; }

--puff 값이 한 입마다 0.05 씩 불어나 calc 로 볼의 크기에 그대로 반영되고, 떨어지는 부스러기가 프레임 사이를 채워 누적면적 11.737% 를 유지했습니다.

css 캐릭터 애니메이션은 어디에 두면 효과가 있나?

일이 끝났음을 한 번 더 확인시키는 자리가 첫 곳입니다. 로그인 완료의 하트 눈(01), 댓글 남기기 성공의 웃음(03), 스티커 붙였을 때의 팝(05)처럼 성공 화면의 캐릭터는 문구 없이도 처리가 됐다는 것을 얼굴로 말합니다. 귀여운 애니메이션 캐릭터 일러스트를 따로 그려 넣지 않아도 도형 몇 개의 표정 변화가 같은 역할을 합니다.

기다림을 달래는 자리가 둘째입니다. 업로드 중의 강아지(07)는 꼬리 속도로 진행을, 시작 전의 젤리(02)는 출렁임으로 긴장을 풀어 줍니다. 진행 바 옆에 백 퍼센트를 붙이는 대신 캐릭터가 점점 신나는 모습으로 같은 정보를 전하는 셈입니다.

사람과 주고받는 자리가 셋째입니다. 스크롤 안내 걷기(04), 상담 인사 말풍선(06), 좋아요 하트(08), 하루 네 번 체크인 쿠키(09)는 캐릭터가 화면의 장식이 아니라 대화 상대로 나섭니다. 다만 한 화면에 한 마리가 원칙입니다 — 아홉 마리를 한 페이지에 다 두면 귀여움이 시끄러움이 되고 정체성이 흐려집니다.

어디서 깨지는가 — 함정

깜빡임만 두면 대표 화면이 눈 뜬 정지 장면이 된다

깜빡임은 2초 중 40~54% 의 짧은 구간이라, 그것만 두면 24장 샘플 대부분이 눈을 뜬 채 멈춘 얼굴이 됩니다. 01 은 앞구간에 하트 박동 두 번을 넣고 뒷구간에 뺨 발그레를 넣어 프레임을 메웠고, 그 결과가 움직인 프레임 11/23 입니다. 아홉 마리 묶음의 비밀번호는 v8539tgs 이고, 격자 카드마다 보이는 대표 화면도 같은 측정에서 뽑은 장면입니다.

원점이 틀리면 캐릭터가 바닥에서 미끄러진다

웃는 콩알(03)의 기울기 원점을 몸 중심에 두면 웃을 때마다 발이 바닥에서 밀려 떠 보입니다. 발바닥으로 옮기는 한 줄로 해결되고, 강아지(07)의 꼬리·귀·고개도 각각 뿌리·붙은 위·목에 원점을 두고서야 자연스럽게 흔들립니다. SVG 안의 다리(04)는 transform-box: view-box 를 함께 써야 축이 viewBox 좌표로 잡힙니다.

페이드로 지우면 반투명 유령이 남는다

표정 바꾸기(05)와 말풍선 사라짐(06)을 opacity 로 옮기면 중간 프레임이 전부 반투명이라 두 표정·두 풍선이 한 장에 겹쳐 찍힙니다. 눈은 두 벌을 겹쳐 visibility 컷으로 골라 끼우고, 하트(07·08)와 부스러기(09)는 페이드 대신 크기를 0 까지 줄여 없앴습니다.

변형 세 가지와 접근성

변수 세 개를 바꾸면 아홉 마리의 성격이 함께 움직입니다.

이름 바꾼 값 느낌
duration $dur-loop 2s → 1s 깜빡임과 출렁임이 두 배로 빨라져 더 겁 많은 캐릭터가 된다
easing $ease-pop → $ease-spring 도약감이 줄고 미끄러지듯 잦아든다
color $subject-pink → $subject-mint 캔디 핑크 캐릭터가 상큼 민트로 옷을 갈아입는다

아홉 마리 전부 누르는 영역은 진짜 <button> 에 aria-label 을 달았고, 눌린 상태는 01·06 이 aria-pressed 로, 나머지는 data-level·data-speed·data-bite 속성 하나로 알립니다. 횟수를 세는 젤리·스티커·하트의 카운터는 장식이라 aria-hidden 이고 횟수 소식은 단추 라벨이 대신 전합니다. prefers-reduced-motion: reduce 에서는 아홉 루프가 전부 멈추고 각자 가장 읽히는 정지 장면 한 장 — 눈 뜬 하트 얼굴, 다 그려진 걷기 캐릭터, 앉아 기다리는 강아지 — 이 남으며, 그 블록의 선언에는 .is-demo 루프 쪽 특이도를 이기도록 !important 를 붙였습니다. 캐릭터의 재료가 이미지가 아니라 텍스트로 쓴 도형이라, 받은 파일을 열면 브라우저에서 바로 돌아갑니다.

이웃 걸음마: 마스코트 애니메이션은 관절 달린 캐릭터를, CSS 장면 그리기는 배경 통째 장면을 다룹니다. 원점 계산은 MDN transform-origin 문서, 튀는 느낌의 수치는 animation-timing-function 문서, 스스로 그리는 선은 stroke-dashoffset 문서, 쿠키 물림은 clip-path 문서, 눌림 알림은 aria-pressed 문서에 근거가 있습니다.

FAQ

애니메이션 쉬운 귀여운 캐릭터를 만들려면 그림을 잘 그려야 하나요

아니요, 01 의 얼굴은 원 하나에 하트 두 개, 뺨 두 개, 반원 입 하나를 얹은 것뿐입니다. 반달 눈은 border-top 만 남긴 원호처럼 도형 조합이라 그리기 실력이 필요하지 않고, 배치 비율만 바꾸면 표정이 바뀝니다.

캐릭터를 gif 나 영상으로 넣는 것과 무엇이 다르나요

gif 는 누를 수 없습니다. 아홉 마리는 클릭마다 단계·표정·파티클로 응답하고 화면 크기와 축소 설정에 맞춰 움직임을 끄는 것도 코드에서 처리됩니다. 이미지 파일이 하나도 없으니 따로 내려받을 무게도 0 입니다.

캐릭터를 여러 마리 두면 페이지가 느려지지 않나요

움직임이 전부 transform 과 opacity 로만 이루어져 레이아웃 계산을 다시 돌리지 않습니다. 젤리의 출렁임을 width·height 로 만들면 매 프레임 레이아웃이 돌아 느려지는데, 아홉 마리는 그 비용을 지불하지 않습니다. 다만 한 화면에 한 마리를 지키는 것이 성능보다 먼저입니다.

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

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