- 왜곡 영역 원 레벨 스타일, 중심점, 포인트 핸들, 영역 외곽선 등 캔버스 스타일을 커스터마이징할 수 있도록 `EditorCanvasStyle` 타입을 추가했습니다. - `DistortionEditorProps`에 `canvasStyle` prop을 추가하여 외부에서 캔버스 스타일을 전달받을 수 있도록 했습니다. - `EditorCanvas` 컴포넌트에서 `useMemo`를 사용하여 기본 스타일과 사용자 정의 스타일을 병합하고, 이를 렌더링에 반영하도록 수정했습니다.
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
Languages
TypeScript
90.2%
CSS
5%
GLSL
4.8%