본문 바로가기
개발하기/React

React로 구현하는 인터랙티브 카드 확장 애니메이션 - 중앙에서 퍼지는 9개의 카드 효과(코드 제공)

by lovedeveloping 2025. 1. 29.
반응형

안녕하세요! 오늘은 정말 멋진 인터랙티브 애니메이션을 구현해보려고 합니다. 중앙의 카드를 클릭하면 9개의 카드가 부드럽게 퍼져나가는 효과를 만들어보겠습니다.

사진 1
아무 기능이 없는 화면

주요 기능 설명

 

  1. 중앙 카드를 클릭하면 8개의 카드가 팝업되어 퍼져나가는 효과
  2. 부드러운 이동 애니메이션과 페이드 인/아웃 효과
  3. 각 카드별 고유한 아이콘과 컬러 테마
  4. 호버 시 반응하는 인터랙티브한 효과
  5. 반응형 레이아웃

구현 방법 상세 설명

1. 카드 배치 로직

카드들의 위치는 translate 속성을 사용하여 계산됩니다. 8방향으로 퍼지는 효과를 위해 다음과 같은 위치값을 사용했습니다:

const positions = [
  "translate-x-0 -translate-y-64",    // 상단
  "translate-x-48 -translate-y-48",   // 우상단
  "translate-x-64",                   // 우측
  "translate-x-48 translate-y-48",    // 우하단
  "translate-y-64",                   // 하단
  "-translate-x-48 translate-y-48",   // 좌하단
  "-translate-x-64",                  // 좌측
  "-translate-x-48 -translate-y-48",  // 좌상단
  "translate-x-0 translate-y-0"       // 중앙
];

 

2. 애니메이션 구현

애니메이션은 CSS transition을 활용하여 구현했습니다:

.card {
  transition: all 500ms ease-out;
}

이를 통해 위치 이동, 투명도 변화, 크기 변화가 모두 부드럽게 일어납니다.

3. 상태 관리

React의 useState를 사용하여 카드들의 확장 상태를 관리합니다:

const [isExpanded, setIsExpanded] = useState(false);

활용 방안

이 컴포넌트는 다음과 같은 상황에서 활용하면 좋습니다:

  1. 메뉴 내비게이션
    • 주요 섹션으로 이동하는 메인 메뉴
    • 카테고리 선택 인터페이스
  2. 기능 쇼케이스
    • 제품의 주요 기능 소개
    • 서비스의 핵심 가치 표현
  3. 대시보드
    • 주요 통계 데이터 표시
    • quick action 메뉴

실제 적용 예시

// App.js나 페이지 컴포넌트에서 사용
import ExpandingCards from './components/ExpandingCards';

function App() {
  return (
    <div className="app">
      <ExpandingCards />
    </div>
  );
}

사진 2
가운데 버튼 클릭 시

전체 코드

더보기
import React, { useState } from 'react';
import { Sparkles, Code, Coffee, Music, Camera, Heart, Star, Moon, Sun } from 'lucide-react';

const ExpandingCards = () => {
  const [isExpanded, setIsExpanded] = useState(false);

  const cards = [
    { icon: Code, title: "개발", color: "bg-blue-500" },
    { icon: Coffee, title: "디자인", color: "bg-amber-500" },
    { icon: Music, title: "음악", color: "bg-purple-500" },
    { icon: Camera, title: "사진", color: "bg-green-500" },
    { icon: Heart, title: "건강", color: "bg-red-500" },
    { icon: Star, title: "즐겨찾기", color: "bg-yellow-500" },
    { icon: Moon, title: "다크모드", color: "bg-indigo-500" },
    { icon: Sun, title: "라이트모드", color: "bg-orange-500" },
    { icon: Sparkles, title: "특별기능", color: "bg-pink-500" }
  ];

  const getCardPosition = (index) => {
    if (!isExpanded) return "";
    
    const positions = [
      "translate-x-0 -translate-y-64", // top
      "translate-x-48 -translate-y-48", // top-right
      "translate-x-64", // right
      "translate-x-48 translate-y-48", // bottom-right
      "translate-y-64", // bottom
      "-translate-x-48 translate-y-48", // bottom-left
      "-translate-x-64", // left
      "-translate-x-48 -translate-y-48", // top-left
      "translate-x-0 translate-y-0" // center
    ];
    
    return positions[index];
  };

  return (
    <div className="min-h-screen bg-gray-100 p-8 flex items-center justify-center overflow-hidden">
      <div className="relative">
        {cards.map((card, index) => {
          const Icon = card.icon;
          return (
            <div
              key={index}
              className={`absolute w-48 h-48 ${card.color} rounded-2xl shadow-lg transition-all duration-500 ease-out cursor-pointer
                ${isExpanded ? 'opacity-100 ' + getCardPosition(index) : 'opacity-0 scale-50'}
                ${index === cards.length - 1 ? 'relative' : ''}`}
              onClick={() => setIsExpanded(!isExpanded)}
            >
              <div className="h-full flex flex-col items-center justify-center space-y-4 text-white">
                <Icon className="w-12 h-12" />
                <span className="text-lg font-semibold">{card.title}</span>
              </div>
              
              {/* Hover effect overlay */}
              <div className="absolute inset-0 bg-white/10 rounded-2xl opacity-0 hover:opacity-100 transition-opacity duration-300" />
            </div>
          );
        })}
      </div>
    </div>
  );
};

export default ExpandingCards;

마무리

지금까지 중앙에서 퍼져나가는 카드 애니메이션 효과를 구현해보았습니다. 이러한 인터랙티브한 요소는 사용자의 관심을 끌고 웹사이트에 생동감을 더해줄 수 있습니다. 실제 프로젝트에 적용하실 때는 프로젝트의 성격과 타겟 사용자의 특성을 고려하여 적절히 커스터마이징하시기 바랍니다.

더 나아가 다음과 같은 기능을 추가해볼 수 있습니다:

  • 카드 클릭 시 상세 정보 표시
  • 드래그 앤 드롭으로 카드 위치 변경
  • 다양한 테마 컬러 지원

이 컴포넌트가 여러분의 프로젝트에 도움이 되길 바랍니다! 궁금한 점이나 추가 기능 요청은 댓글로 남겨주세요. 다음에는 더 흥미로운 인터랙티브 컴포넌트를 소개하도록 하겠습니다. 감사합니다!

반응형