BaekRyang ddcf8b463a feat: Improve mouse interaction to affect multiple areas
- 마우스가 닿는 모든 영역에 왜곡 효과가 적용되도록 수정했습니다.
- 기존에는 마우스가 처음 닿는 단일 영역에만 효과가 적용되었으나, 이제는 마우스 커서가 영역을 벗어나도 해당 영역에 대한 스프링 물리 효과가 유지되도록 변경되었습니다.
- `useMouseInteraction` 훅에서 `interactingAreaIndex` 대신 `interactingAreaIndices` (Set)를 사용하여 여러 영역을 동시에 추적합니다.
- 영역 진입 시 스프링이 리셋되고, 영역 이탈 시 평형 상태로 복귀하는 로직이 추가되었습니다.
2025-11-05 15:31:11 +09:00
2025-11-05 11:21:28 +09:00
2025-11-04 10:15:34 +09:00
2025-11-04 10:15:34 +09:00
2025-11-04 10:15:34 +09:00
2025-11-04 10:15:34 +09:00

Responsive Image Canvas

GPU 가속 이미지 왜곡 효과를 제공하는 React 컴포넌트 라이브러리입니다. Three.js와 GLSL 셰이더를 사용하여 실시간 이미지 왜곡 애니메이션을 구현합니다.

특징

  • 🚀 GPU 가속 렌더링 (Three.js + WebGL)
  • 🎨 최대 8개의 독립적인 왜곡 영역 지원
  • 60fps 실시간 애니메이션
  • 🎯 정규화된 좌표계 (0.0 - 1.0)
  • 🔧 TypeScript 완벽 지원
  • 📦 ESM & CommonJS 모두 지원

설치

npm install responsive-image-canvas

Peer Dependencies

npm install react react-dom three

기본 사용법

import { ImageDistortion, DistortionArea } from 'responsive-image-canvas';

const areas: DistortionArea[] = [
  {
    id: 'area-1',
    basePoints: [
      { x: 0.2, y: 0.2 },  // 좌상단
      { x: 0.4, y: 0.2 },  // 우상단
      { x: 0.4, y: 0.4 },  // 우하단
      { x: 0.2, y: 0.4 },  // 좌하단
    ],
    movement: {
      vectorA: { x: 0.1, y: 0.1 },
      vectorB: { x: -0.1, y: -0.1 },
      duration: 2.0,
      easing: 'easeInOut',
    },
    distortionStrength: 0.5,
    progress: 0,
    dragVector: { x: 0, y: 0 },
  },
];

function App() {
  return (
    <div style={{ width: '800px', height: '600px' }}>
      <ImageDistortion
        imageSrc="/path/to/image.jpg"
        areas={areas}
        isPlaying={true}
      />
    </div>
  );
}

Props

ImageDistortionProps

Prop 타입 필수 기본값 설명
imageSrc string - 이미지 소스 URL
areas DistortionArea[] - 왜곡 영역 배열
vertexShaderPath string /shaders/distortion.vert.glsl 커스텀 버텍스 셰이더 경로
fragmentShaderPath string /shaders/distortion.frag.glsl 커스텀 프래그먼트 셰이더 경로
isPlaying boolean true 애니메이션 재생 여부
style CSSProperties - 컨테이너 스타일
className string - 컨테이너 클래스명

타입 정의

DistortionArea

interface DistortionArea {
  id: string;                           // 고유 식별자
  basePoints: [Point, Point, Point, Point];  // 사각형의 네 모서리
  movement: DistortionMovement;         // 애니메이션 설정
  distortionStrength: number;           // 왜곡 강도 (0.0 - 1.0)
  progress: number;                     // 애니메이션 진행도 (0.0 - 1.0)
  dragVector: Point;                    // 현재 드래그 벡터
}

Point

interface Point {
  x: number;  // 0.0 - 1.0 (정규화된 좌표)
  y: number;  // 0.0 - 1.0 (정규화된 좌표)
}

DistortionMovement

interface DistortionMovement {
  vectorA: Point;            // 시작 벡터
  vectorB: Point;            // 종료 벡터
  duration: number;          // 지속 시간 (초)
  easing: EasingFunction;    // 이징 함수
}

EasingFunction

type EasingFunction =
  | 'linear'
  | 'easeIn'
  | 'easeOut'
  | 'easeInOut'
  | 'easeInQuad'
  | 'easeOutQuad';

고급 사용법

영역 동적 추가/제거

function DynamicDistortion() {
  const [areas, setAreas] = useState<DistortionArea[]>([]);

  const addArea = () => {
    const newArea: DistortionArea = {
      id: `area-${Date.now()}`,
      basePoints: [
        { x: 0.3, y: 0.3 },
        { x: 0.7, y: 0.3 },
        { x: 0.7, y: 0.7 },
        { x: 0.3, y: 0.7 },
      ],
      movement: {
        vectorA: { x: 0.15, y: 0 },
        vectorB: { x: -0.15, y: 0 },
        duration: 3.0,
        easing: 'easeInOut',
      },
      distortionStrength: 0.6,
      progress: 0,
      dragVector: { x: 0, y: 0 },
    };

    setAreas([...areas, newArea]);
  };

  return (
    <div>
      <button onClick={addArea}>영역 추가</button>
      <ImageDistortion
        imageSrc="/image.jpg"
        areas={areas}
      />
    </div>
  );
}

유틸리티 함수 사용

import { DEFAULT_AREA, applyEasing } from 'responsive-image-canvas';

// 기본 설정값 사용
const newArea = {
  ...DEFAULT_AREA,
  id: 'my-area',
  basePoints: [/* ... */],
};

// 이징 함수 직접 사용
const easedValue = applyEasing(0.5, 'easeInOut');
console.log(easedValue); // 0.5

셰이더 파일

패키지는 기본 셰이더 파일을 포함하고 있습니다:

  • dist/distortion.vert.glsl - 버텍스 셰이더
  • dist/distortion.frag.glsl - 프래그먼트 셰이더

웹 서버에서 이 파일들을 정적 파일로 제공해야 합니다.

Vite 설정 예시

// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  publicDir: 'public',
  // node_modules의 셰이더 파일을 복사
  build: {
    rollupOptions: {
      output: {
        assetFileNames: 'assets/[name].[ext]',
      },
    },
  },
});

셰이더 파일을 public 폴더로 복사:

cp node_modules/responsive-image-canvas/dist/*.glsl public/shaders/

성능 최적화

1. 영역 수 제한

최대 8개의 영역까지 지원하지만, 성능을 위해 4개 이하를 권장합니다.

2. 이미지 크기 최적화

큰 이미지는 성능에 영향을 줄 수 있습니다. 적절한 크기로 리사이징하세요.

3. 애니메이션 일시정지

필요하지 않을 때는 isPlaying={false}로 설정하세요.

제한사항

  • WebGL을 지원하지 않는 브라우저에서는 동작하지 않습니다
  • 모바일 환경에서는 성능이 제한될 수 있습니다
  • 최대 8개의 왜곡 영역만 지원합니다

브라우저 지원

  • Chrome 60+
  • Firefox 60+
  • Safari 12+
  • Edge 79+

라이선스

MIT

기여

이슈와 PR을 환영합니다!

관련 프로젝트

Description
No description provided
Readme 2.5 MiB
Languages
TypeScript 90.2%
CSS 5%
GLSL 4.8%