255 lines
5.8 KiB
Markdown
255 lines
5.8 KiB
Markdown
# Responsive Image Canvas
|
|
|
|
GPU 가속 이미지 왜곡 효과를 제공하는 React 컴포넌트 라이브러리입니다. Three.js와 GLSL 셰이더를 사용하여 실시간 이미지 왜곡 애니메이션을 구현합니다.
|
|
|
|
## 특징
|
|
|
|
- 🚀 GPU 가속 렌더링 (Three.js + WebGL)
|
|
- 🎨 최대 8개의 독립적인 왜곡 영역 지원
|
|
- ⚡ 60fps 실시간 애니메이션
|
|
- 🎯 정규화된 좌표계 (0.0 - 1.0)
|
|
- 🔧 TypeScript 완벽 지원
|
|
- 📦 ESM & CommonJS 모두 지원
|
|
|
|
## 설치
|
|
|
|
```bash
|
|
npm install responsive-image-canvas
|
|
```
|
|
|
|
### Peer Dependencies
|
|
|
|
```bash
|
|
npm install react react-dom three
|
|
```
|
|
|
|
## 기본 사용법
|
|
|
|
```tsx
|
|
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`
|
|
|
|
```typescript
|
|
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`
|
|
|
|
```typescript
|
|
interface Point {
|
|
x: number; // 0.0 - 1.0 (정규화된 좌표)
|
|
y: number; // 0.0 - 1.0 (정규화된 좌표)
|
|
}
|
|
```
|
|
|
|
### `DistortionMovement`
|
|
|
|
```typescript
|
|
interface DistortionMovement {
|
|
vectorA: Point; // 시작 벡터
|
|
vectorB: Point; // 종료 벡터
|
|
duration: number; // 지속 시간 (초)
|
|
easing: EasingFunction; // 이징 함수
|
|
}
|
|
```
|
|
|
|
### `EasingFunction`
|
|
|
|
```typescript
|
|
type EasingFunction =
|
|
| 'linear'
|
|
| 'easeIn'
|
|
| 'easeOut'
|
|
| 'easeInOut'
|
|
| 'easeInQuad'
|
|
| 'easeOutQuad';
|
|
```
|
|
|
|
## 고급 사용법
|
|
|
|
### 영역 동적 추가/제거
|
|
|
|
```tsx
|
|
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>
|
|
);
|
|
}
|
|
```
|
|
|
|
### 유틸리티 함수 사용
|
|
|
|
```tsx
|
|
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 설정 예시
|
|
|
|
```typescript
|
|
// vite.config.ts
|
|
import { defineConfig } from 'vite';
|
|
|
|
export default defineConfig({
|
|
publicDir: 'public',
|
|
// node_modules의 셰이더 파일을 복사
|
|
build: {
|
|
rollupOptions: {
|
|
output: {
|
|
assetFileNames: 'assets/[name].[ext]',
|
|
},
|
|
},
|
|
},
|
|
});
|
|
```
|
|
|
|
셰이더 파일을 public 폴더로 복사:
|
|
|
|
```bash
|
|
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을 환영합니다!
|
|
|
|
## 관련 프로젝트
|
|
|
|
- [Three.js](https://threejs.org/)
|
|
- [React Three Fiber](https://github.com/pmndrs/react-three-fiber)
|