Compare commits
No commits in common. "6d9dd082c16c24fa23d55a67e7eccdd8cb3a2246" and "6b6c8d8fd0a236a28832c8f5e93428f090d14977" have entirely different histories.
6d9dd082c1
...
6b6c8d8fd0
1
.npmrc
1
.npmrc
@ -1 +0,0 @@
|
||||
//git.bnovalab.com/api/packages/baekryang/npm/:_authToken=a2ed709f39e95662493a92305555a4bf70f6fe10
|
||||
10
dist/distortion.frag.glsl
vendored
10
dist/distortion.frag.glsl
vendored
@ -4,7 +4,6 @@ uniform vec2 u_points[32]; // 최대 8영역 × 4포인트 (정규화된
|
||||
uniform int u_numAreas;
|
||||
uniform vec2 u_dragVectors[8]; // 드래그 벡터 (정규화된 좌표 0-1)
|
||||
uniform float u_distortionStrengths[8];
|
||||
uniform float u_lensEffects[8];
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
@ -75,15 +74,6 @@ void main() {
|
||||
// dragVector는 정규화된 좌표(0-1)이므로 바로 사용
|
||||
vec2 distortion = u_dragVectors[i] * influence * u_distortionStrengths[i];
|
||||
texCoord += distortion;
|
||||
|
||||
// 렌즈 왜곡 효과 (방사형 UV 왜곡)
|
||||
if (abs(u_lensEffects[i]) > 0.001) {
|
||||
vec2 centered = uv_local - vec2(0.5);
|
||||
float dist2 = dot(centered, centered);
|
||||
float lensK = u_lensEffects[i] * 2.0; // 강도 스케일링
|
||||
vec2 lensDistortion = centered * lensK * dist2;
|
||||
texCoord += lensDistortion * u_distortionStrengths[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
dist/index.d.mts
vendored
15
dist/index.d.mts
vendored
@ -11,7 +11,7 @@ interface Point {
|
||||
/**
|
||||
* 애니메이션 이징 함수 타입
|
||||
*/
|
||||
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'steps2' | 'steps3' | 'steps4' | 'steps5' | 'steps6' | 'steps8' | 'steps10';
|
||||
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic';
|
||||
/**
|
||||
* 내장 모션 프리셋 타입
|
||||
*/
|
||||
@ -68,11 +68,6 @@ interface DistortionArea {
|
||||
influenceRadius: number;
|
||||
maxStrength: number;
|
||||
};
|
||||
/** 렌즈 효과 설정 (선택사항) */
|
||||
lensEffect?: {
|
||||
/** 렌즈 강도 (양수: 볼록, 음수: 오목, 0: 없음, 범위: -1.0 ~ 1.0) */
|
||||
strength: number;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 영역 충돌 감지를 위한 경계 상자
|
||||
@ -101,8 +96,6 @@ interface ShaderUniforms {
|
||||
u_dragVectors: THREE.IUniform<Float32Array>;
|
||||
/** 각 영역의 왜곡 강도 배열 */
|
||||
u_distortionStrengths: THREE.IUniform<Float32Array>;
|
||||
/** 각 영역의 렌즈 효과 강도 배열 */
|
||||
u_lensEffects: THREE.IUniform<Float32Array>;
|
||||
}
|
||||
/**
|
||||
* 셰이더 설정
|
||||
@ -212,6 +205,8 @@ interface ImageDistortionProps {
|
||||
vertexShaderPath?: string;
|
||||
/** 프래그먼트 셰이더 경로 (선택사항) */
|
||||
fragmentShaderPath?: string;
|
||||
/** 애니메이션 재생 여부 */
|
||||
isPlaying?: boolean;
|
||||
/** 컨테이너 스타일 */
|
||||
style?: React$1.CSSProperties;
|
||||
/** 컨테이너 클래스명 */
|
||||
@ -395,8 +390,6 @@ declare const SHADER_CONFIG: {
|
||||
readonly MAX_DRAG_VECTORS: 8;
|
||||
/** 최대 강도 배열 크기 */
|
||||
readonly MAX_STRENGTHS: 8;
|
||||
/** 최대 렌즈 효과 배열 크기 */
|
||||
readonly MAX_LENS_EFFECTS: 8;
|
||||
};
|
||||
/**
|
||||
* 애니메이션 관련 설정
|
||||
@ -427,8 +420,6 @@ declare const DEFAULT_AREA: {
|
||||
readonly x: -0.1;
|
||||
readonly y: -0.1;
|
||||
};
|
||||
/** 기본 렌즈 효과 강도 */
|
||||
readonly LENS_STRENGTH: 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
15
dist/index.d.ts
vendored
15
dist/index.d.ts
vendored
@ -11,7 +11,7 @@ interface Point {
|
||||
/**
|
||||
* 애니메이션 이징 함수 타입
|
||||
*/
|
||||
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'steps2' | 'steps3' | 'steps4' | 'steps5' | 'steps6' | 'steps8' | 'steps10';
|
||||
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic';
|
||||
/**
|
||||
* 내장 모션 프리셋 타입
|
||||
*/
|
||||
@ -68,11 +68,6 @@ interface DistortionArea {
|
||||
influenceRadius: number;
|
||||
maxStrength: number;
|
||||
};
|
||||
/** 렌즈 효과 설정 (선택사항) */
|
||||
lensEffect?: {
|
||||
/** 렌즈 강도 (양수: 볼록, 음수: 오목, 0: 없음, 범위: -1.0 ~ 1.0) */
|
||||
strength: number;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 영역 충돌 감지를 위한 경계 상자
|
||||
@ -101,8 +96,6 @@ interface ShaderUniforms {
|
||||
u_dragVectors: THREE.IUniform<Float32Array>;
|
||||
/** 각 영역의 왜곡 강도 배열 */
|
||||
u_distortionStrengths: THREE.IUniform<Float32Array>;
|
||||
/** 각 영역의 렌즈 효과 강도 배열 */
|
||||
u_lensEffects: THREE.IUniform<Float32Array>;
|
||||
}
|
||||
/**
|
||||
* 셰이더 설정
|
||||
@ -212,6 +205,8 @@ interface ImageDistortionProps {
|
||||
vertexShaderPath?: string;
|
||||
/** 프래그먼트 셰이더 경로 (선택사항) */
|
||||
fragmentShaderPath?: string;
|
||||
/** 애니메이션 재생 여부 */
|
||||
isPlaying?: boolean;
|
||||
/** 컨테이너 스타일 */
|
||||
style?: React$1.CSSProperties;
|
||||
/** 컨테이너 클래스명 */
|
||||
@ -395,8 +390,6 @@ declare const SHADER_CONFIG: {
|
||||
readonly MAX_DRAG_VECTORS: 8;
|
||||
/** 최대 강도 배열 크기 */
|
||||
readonly MAX_STRENGTHS: 8;
|
||||
/** 최대 렌즈 효과 배열 크기 */
|
||||
readonly MAX_LENS_EFFECTS: 8;
|
||||
};
|
||||
/**
|
||||
* 애니메이션 관련 설정
|
||||
@ -427,8 +420,6 @@ declare const DEFAULT_AREA: {
|
||||
readonly x: -0.1;
|
||||
readonly y: -0.1;
|
||||
};
|
||||
/** 기본 렌즈 효과 강도 */
|
||||
readonly LENS_STRENGTH: 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
79
dist/index.js
vendored
79
dist/index.js
vendored
@ -96,8 +96,7 @@ var ThreeScene = class {
|
||||
u_numAreas: { value: 0 },
|
||||
u_dragVectors: { value: new Float32Array(16) },
|
||||
// 8벡터 × 2(x,y)
|
||||
u_distortionStrengths: { value: new Float32Array(8) },
|
||||
u_lensEffects: { value: new Float32Array(8) }
|
||||
u_distortionStrengths: { value: new Float32Array(8) }
|
||||
};
|
||||
this.handleResize();
|
||||
window.addEventListener("resize", this.handleResize);
|
||||
@ -243,7 +242,6 @@ var ShaderManager = class {
|
||||
};
|
||||
|
||||
// src/utils/easing.ts
|
||||
var createStepEasing = (steps) => (t) => Math.floor(t * steps) / steps;
|
||||
var easingFunctions = {
|
||||
linear: (t) => t,
|
||||
easeIn: (t) => t * t,
|
||||
@ -252,14 +250,7 @@ var easingFunctions = {
|
||||
easeInQuad: (t) => t * t,
|
||||
easeOutQuad: (t) => t * (2 - t),
|
||||
easeInCubic: (t) => t * t * t,
|
||||
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
|
||||
steps2: createStepEasing(2),
|
||||
steps3: createStepEasing(3),
|
||||
steps4: createStepEasing(4),
|
||||
steps5: createStepEasing(5),
|
||||
steps6: createStepEasing(6),
|
||||
steps8: createStepEasing(8),
|
||||
steps10: createStepEasing(10)
|
||||
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3)
|
||||
};
|
||||
var applyEasing = (progress, easingType) => {
|
||||
const clampedProgress = Math.max(0, Math.min(1, progress));
|
||||
@ -817,9 +808,7 @@ var SHADER_CONFIG = {
|
||||
/** 최대 드래그 벡터 개수 */
|
||||
MAX_DRAG_VECTORS: 8,
|
||||
/** 최대 강도 배열 크기 */
|
||||
MAX_STRENGTHS: 8,
|
||||
/** 최대 렌즈 효과 배열 크기 */
|
||||
MAX_LENS_EFFECTS: 8
|
||||
MAX_STRENGTHS: 8
|
||||
};
|
||||
var ANIMATION_CONFIG = {
|
||||
/** 목표 FPS */
|
||||
@ -837,9 +826,7 @@ var DEFAULT_AREA = {
|
||||
/** 기본 벡터 A */
|
||||
VECTOR_A: { x: 0.1, y: 0.1 },
|
||||
/** 기본 벡터 B */
|
||||
VECTOR_B: { x: -0.1, y: -0.1 },
|
||||
/** 기본 렌즈 효과 강도 */
|
||||
LENS_STRENGTH: 0
|
||||
VECTOR_B: { x: -0.1, y: -0.1 }
|
||||
};
|
||||
|
||||
// src/components/ImageDistortion.tsx
|
||||
@ -849,6 +836,7 @@ var ImageDistortion = ({
|
||||
areas,
|
||||
vertexShaderPath,
|
||||
fragmentShaderPath,
|
||||
isPlaying = true,
|
||||
style,
|
||||
className,
|
||||
mouseInteraction
|
||||
@ -971,16 +959,11 @@ var ImageDistortion = ({
|
||||
currentAreas.forEach((area, index) => {
|
||||
strengths[index] = area.distortionStrength;
|
||||
});
|
||||
const lensEffects = new Float32Array(SHADER_CONFIG.MAX_LENS_EFFECTS);
|
||||
currentAreas.forEach((area, index) => {
|
||||
lensEffects[index] = area.lensEffect?.strength ?? 0;
|
||||
});
|
||||
sceneRef.current.updateUniforms({
|
||||
u_numAreas: { value: currentAreas.length },
|
||||
u_points: { value: points },
|
||||
u_dragVectors: { value: dragVectors },
|
||||
u_distortionStrengths: { value: strengths },
|
||||
u_lensEffects: { value: lensEffects }
|
||||
u_distortionStrengths: { value: strengths }
|
||||
});
|
||||
sceneRef.current.render();
|
||||
}, [currentAreas, isReady]);
|
||||
@ -1007,7 +990,7 @@ var ImageDistortion = ({
|
||||
return updatedAreas;
|
||||
});
|
||||
}, [isReady, mouseInteraction, mouseInteractionHook]);
|
||||
useAnimationFrame(animationCallback, true);
|
||||
useAnimationFrame(animationCallback, isPlaying || mouseInteraction?.enabled || false);
|
||||
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
||||
"div",
|
||||
{
|
||||
@ -1110,14 +1093,7 @@ var EASING_OPTIONS = [
|
||||
{ value: "easeOut", label: "\uAC10\uC18D (Ease Out)" },
|
||||
{ value: "easeInOut", label: "\uAC00\uAC10\uC18D (Ease In Out)" },
|
||||
{ value: "easeInQuad", label: "\uAC00\uC18D\xB2 (Ease In Quad)" },
|
||||
{ value: "easeOutQuad", label: "\uAC10\uC18D\xB2 (Ease Out Quad)" },
|
||||
{ value: "steps2", label: "2\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps3", label: "3\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps4", label: "4\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps5", label: "5\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps6", label: "6\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps8", label: "8\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps10", label: "10\uB2E8\uACC4 \uC2A4\uD15D" }
|
||||
{ value: "easeOutQuad", label: "\uAC10\uC18D\xB2 (Ease Out Quad)" }
|
||||
];
|
||||
var ParameterPanel = ({ area, onUpdateArea }) => {
|
||||
if (!area) {
|
||||
@ -1179,26 +1155,6 @@ var ParameterPanel = ({ area, onUpdateArea }) => {
|
||||
}
|
||||
)
|
||||
] }),
|
||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "parameter-group", children: [
|
||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { children: [
|
||||
"\uB80C\uC988 \uD6A8\uACFC: ",
|
||||
(area.lensEffect?.strength ?? 0) > 0 ? "\uBCFC\uB85D " : (area.lensEffect?.strength ?? 0) < 0 ? "\uC624\uBAA9 " : "",
|
||||
((area.lensEffect?.strength ?? 0) * 100).toFixed(0),
|
||||
"%"
|
||||
] }),
|
||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
||||
"input",
|
||||
{
|
||||
type: "range",
|
||||
min: "-1",
|
||||
max: "1",
|
||||
step: "0.01",
|
||||
value: area.lensEffect?.strength ?? 0,
|
||||
onChange: (e) => onUpdateArea({ lensEffect: { strength: parseFloat(e.target.value) } }),
|
||||
className: "slider"
|
||||
}
|
||||
)
|
||||
] }),
|
||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "parameter-group", children: [
|
||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { children: "\uD3EC\uC778\uD2B8 \uC88C\uD45C (\uCE94\uBC84\uC2A4\uC5D0\uC11C \uB4DC\uB798\uADF8)" }),
|
||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "points-display", children: area.basePoints.map((point, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "point-coord", children: [
|
||||
@ -1386,18 +1342,9 @@ var EditorCanvas = ({
|
||||
}), [customStyle]);
|
||||
(0, import_react6.useEffect)(() => {
|
||||
if (!containerRef.current) return;
|
||||
const updateSize = () => {
|
||||
if (!containerRef.current) return;
|
||||
const rect = containerRef.current.getBoundingClientRect();
|
||||
setCanvasSize({ width: rect.width, height: rect.height });
|
||||
};
|
||||
updateSize();
|
||||
const resizeObserver = new ResizeObserver(updateSize);
|
||||
resizeObserver.observe(containerRef.current);
|
||||
return () => {
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
}, []);
|
||||
const rect = containerRef.current.getBoundingClientRect();
|
||||
setCanvasSize({ width: rect.width, height: rect.height });
|
||||
}, [width, height]);
|
||||
const selectedArea = areas.find((a) => a.id === selectedAreaId);
|
||||
const isPointInPolygon2 = (0, import_react6.useCallback)((point, polygon) => {
|
||||
let inside = false;
|
||||
@ -1583,8 +1530,8 @@ var EditorCanvas = ({
|
||||
ref: containerRef,
|
||||
className: "editor-canvas",
|
||||
style: {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
width,
|
||||
height,
|
||||
position: "relative",
|
||||
cursor: showEditor ? getCursorStyle() : "default",
|
||||
pointerEvents: showEditor ? "auto" : "none",
|
||||
|
||||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
79
dist/index.mjs
vendored
79
dist/index.mjs
vendored
@ -36,8 +36,7 @@ var ThreeScene = class {
|
||||
u_numAreas: { value: 0 },
|
||||
u_dragVectors: { value: new Float32Array(16) },
|
||||
// 8벡터 × 2(x,y)
|
||||
u_distortionStrengths: { value: new Float32Array(8) },
|
||||
u_lensEffects: { value: new Float32Array(8) }
|
||||
u_distortionStrengths: { value: new Float32Array(8) }
|
||||
};
|
||||
this.handleResize();
|
||||
window.addEventListener("resize", this.handleResize);
|
||||
@ -183,7 +182,6 @@ var ShaderManager = class {
|
||||
};
|
||||
|
||||
// src/utils/easing.ts
|
||||
var createStepEasing = (steps) => (t) => Math.floor(t * steps) / steps;
|
||||
var easingFunctions = {
|
||||
linear: (t) => t,
|
||||
easeIn: (t) => t * t,
|
||||
@ -192,14 +190,7 @@ var easingFunctions = {
|
||||
easeInQuad: (t) => t * t,
|
||||
easeOutQuad: (t) => t * (2 - t),
|
||||
easeInCubic: (t) => t * t * t,
|
||||
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
|
||||
steps2: createStepEasing(2),
|
||||
steps3: createStepEasing(3),
|
||||
steps4: createStepEasing(4),
|
||||
steps5: createStepEasing(5),
|
||||
steps6: createStepEasing(6),
|
||||
steps8: createStepEasing(8),
|
||||
steps10: createStepEasing(10)
|
||||
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3)
|
||||
};
|
||||
var applyEasing = (progress, easingType) => {
|
||||
const clampedProgress = Math.max(0, Math.min(1, progress));
|
||||
@ -757,9 +748,7 @@ var SHADER_CONFIG = {
|
||||
/** 최대 드래그 벡터 개수 */
|
||||
MAX_DRAG_VECTORS: 8,
|
||||
/** 최대 강도 배열 크기 */
|
||||
MAX_STRENGTHS: 8,
|
||||
/** 최대 렌즈 효과 배열 크기 */
|
||||
MAX_LENS_EFFECTS: 8
|
||||
MAX_STRENGTHS: 8
|
||||
};
|
||||
var ANIMATION_CONFIG = {
|
||||
/** 목표 FPS */
|
||||
@ -777,9 +766,7 @@ var DEFAULT_AREA = {
|
||||
/** 기본 벡터 A */
|
||||
VECTOR_A: { x: 0.1, y: 0.1 },
|
||||
/** 기본 벡터 B */
|
||||
VECTOR_B: { x: -0.1, y: -0.1 },
|
||||
/** 기본 렌즈 효과 강도 */
|
||||
LENS_STRENGTH: 0
|
||||
VECTOR_B: { x: -0.1, y: -0.1 }
|
||||
};
|
||||
|
||||
// src/components/ImageDistortion.tsx
|
||||
@ -789,6 +776,7 @@ var ImageDistortion = ({
|
||||
areas,
|
||||
vertexShaderPath,
|
||||
fragmentShaderPath,
|
||||
isPlaying = true,
|
||||
style,
|
||||
className,
|
||||
mouseInteraction
|
||||
@ -911,16 +899,11 @@ var ImageDistortion = ({
|
||||
currentAreas.forEach((area, index) => {
|
||||
strengths[index] = area.distortionStrength;
|
||||
});
|
||||
const lensEffects = new Float32Array(SHADER_CONFIG.MAX_LENS_EFFECTS);
|
||||
currentAreas.forEach((area, index) => {
|
||||
lensEffects[index] = area.lensEffect?.strength ?? 0;
|
||||
});
|
||||
sceneRef.current.updateUniforms({
|
||||
u_numAreas: { value: currentAreas.length },
|
||||
u_points: { value: points },
|
||||
u_dragVectors: { value: dragVectors },
|
||||
u_distortionStrengths: { value: strengths },
|
||||
u_lensEffects: { value: lensEffects }
|
||||
u_distortionStrengths: { value: strengths }
|
||||
});
|
||||
sceneRef.current.render();
|
||||
}, [currentAreas, isReady]);
|
||||
@ -947,7 +930,7 @@ var ImageDistortion = ({
|
||||
return updatedAreas;
|
||||
});
|
||||
}, [isReady, mouseInteraction, mouseInteractionHook]);
|
||||
useAnimationFrame(animationCallback, true);
|
||||
useAnimationFrame(animationCallback, isPlaying || mouseInteraction?.enabled || false);
|
||||
return /* @__PURE__ */ jsx(
|
||||
"div",
|
||||
{
|
||||
@ -1050,14 +1033,7 @@ var EASING_OPTIONS = [
|
||||
{ value: "easeOut", label: "\uAC10\uC18D (Ease Out)" },
|
||||
{ value: "easeInOut", label: "\uAC00\uAC10\uC18D (Ease In Out)" },
|
||||
{ value: "easeInQuad", label: "\uAC00\uC18D\xB2 (Ease In Quad)" },
|
||||
{ value: "easeOutQuad", label: "\uAC10\uC18D\xB2 (Ease Out Quad)" },
|
||||
{ value: "steps2", label: "2\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps3", label: "3\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps4", label: "4\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps5", label: "5\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps6", label: "6\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps8", label: "8\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||
{ value: "steps10", label: "10\uB2E8\uACC4 \uC2A4\uD15D" }
|
||||
{ value: "easeOutQuad", label: "\uAC10\uC18D\xB2 (Ease Out Quad)" }
|
||||
];
|
||||
var ParameterPanel = ({ area, onUpdateArea }) => {
|
||||
if (!area) {
|
||||
@ -1119,26 +1095,6 @@ var ParameterPanel = ({ area, onUpdateArea }) => {
|
||||
}
|
||||
)
|
||||
] }),
|
||||
/* @__PURE__ */ jsxs2("div", { className: "parameter-group", children: [
|
||||
/* @__PURE__ */ jsxs2("label", { children: [
|
||||
"\uB80C\uC988 \uD6A8\uACFC: ",
|
||||
(area.lensEffect?.strength ?? 0) > 0 ? "\uBCFC\uB85D " : (area.lensEffect?.strength ?? 0) < 0 ? "\uC624\uBAA9 " : "",
|
||||
((area.lensEffect?.strength ?? 0) * 100).toFixed(0),
|
||||
"%"
|
||||
] }),
|
||||
/* @__PURE__ */ jsx3(
|
||||
"input",
|
||||
{
|
||||
type: "range",
|
||||
min: "-1",
|
||||
max: "1",
|
||||
step: "0.01",
|
||||
value: area.lensEffect?.strength ?? 0,
|
||||
onChange: (e) => onUpdateArea({ lensEffect: { strength: parseFloat(e.target.value) } }),
|
||||
className: "slider"
|
||||
}
|
||||
)
|
||||
] }),
|
||||
/* @__PURE__ */ jsxs2("div", { className: "parameter-group", children: [
|
||||
/* @__PURE__ */ jsx3("label", { children: "\uD3EC\uC778\uD2B8 \uC88C\uD45C (\uCE94\uBC84\uC2A4\uC5D0\uC11C \uB4DC\uB798\uADF8)" }),
|
||||
/* @__PURE__ */ jsx3("div", { className: "points-display", children: area.basePoints.map((point, idx) => /* @__PURE__ */ jsxs2("div", { className: "point-coord", children: [
|
||||
@ -1326,18 +1282,9 @@ var EditorCanvas = ({
|
||||
}), [customStyle]);
|
||||
useEffect4(() => {
|
||||
if (!containerRef.current) return;
|
||||
const updateSize = () => {
|
||||
if (!containerRef.current) return;
|
||||
const rect = containerRef.current.getBoundingClientRect();
|
||||
setCanvasSize({ width: rect.width, height: rect.height });
|
||||
};
|
||||
updateSize();
|
||||
const resizeObserver = new ResizeObserver(updateSize);
|
||||
resizeObserver.observe(containerRef.current);
|
||||
return () => {
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
}, []);
|
||||
const rect = containerRef.current.getBoundingClientRect();
|
||||
setCanvasSize({ width: rect.width, height: rect.height });
|
||||
}, [width, height]);
|
||||
const selectedArea = areas.find((a) => a.id === selectedAreaId);
|
||||
const isPointInPolygon2 = useCallback5((point, polygon) => {
|
||||
let inside = false;
|
||||
@ -1523,8 +1470,8 @@ var EditorCanvas = ({
|
||||
ref: containerRef,
|
||||
className: "editor-canvas",
|
||||
style: {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
width,
|
||||
height,
|
||||
position: "relative",
|
||||
cursor: showEditor ? getCursorStyle() : "default",
|
||||
pointerEvents: showEditor ? "auto" : "none",
|
||||
|
||||
2
dist/index.mjs.map
vendored
2
dist/index.mjs.map
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@baekryang/responsive-image-canvas",
|
||||
"version": "1.2.7",
|
||||
"version": "1.2.1",
|
||||
"publishConfig": {
|
||||
"registry": "https://git.bnovalab.com/api/packages/baekryang/npm/"
|
||||
},
|
||||
|
||||
@ -21,6 +21,8 @@ export interface ImageDistortionProps {
|
||||
vertexShaderPath?: string;
|
||||
/** 프래그먼트 셰이더 경로 (선택사항) */
|
||||
fragmentShaderPath?: string;
|
||||
/** 애니메이션 재생 여부 */
|
||||
isPlaying?: boolean;
|
||||
/** 컨테이너 스타일 */
|
||||
style?: React.CSSProperties;
|
||||
/** 컨테이너 클래스명 */
|
||||
@ -38,6 +40,7 @@ export const ImageDistortion: React.FC<ImageDistortionProps> = ({
|
||||
areas,
|
||||
vertexShaderPath,
|
||||
fragmentShaderPath,
|
||||
isPlaying = true,
|
||||
style,
|
||||
className,
|
||||
mouseInteraction,
|
||||
@ -196,18 +199,11 @@ export const ImageDistortion: React.FC<ImageDistortionProps> = ({
|
||||
strengths[index] = area.distortionStrength;
|
||||
});
|
||||
|
||||
// 렌즈 효과 배열 생성
|
||||
const lensEffects = new Float32Array(SHADER_CONFIG.MAX_LENS_EFFECTS);
|
||||
currentAreas.forEach((area, index) => {
|
||||
lensEffects[index] = area.lensEffect?.strength ?? 0;
|
||||
});
|
||||
|
||||
sceneRef.current.updateUniforms({
|
||||
u_numAreas: { value: currentAreas.length },
|
||||
u_points: { value: points },
|
||||
u_dragVectors: { value: dragVectors },
|
||||
u_distortionStrengths: { value: strengths },
|
||||
u_lensEffects: { value: lensEffects },
|
||||
});
|
||||
|
||||
sceneRef.current.render();
|
||||
@ -247,8 +243,8 @@ export const ImageDistortion: React.FC<ImageDistortionProps> = ({
|
||||
});
|
||||
}, [isReady, mouseInteraction, mouseInteractionHook]);
|
||||
|
||||
// 애니메이션 루프 실행
|
||||
useAnimationFrame(animationCallback, true);
|
||||
// 애니메이션은 항상 실행 (마우스 인터랙션 포함)
|
||||
useAnimationFrame(animationCallback, isPlaying || mouseInteraction?.enabled || false);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@ -62,27 +62,12 @@ export const EditorCanvas: React.FC<EditorCanvasProps> = ({
|
||||
},
|
||||
}), [customStyle]);
|
||||
|
||||
// 컨테이너 크기 측정 (ResizeObserver 사용)
|
||||
// 컨테이너 크기 측정
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
const updateSize = () => {
|
||||
if (!containerRef.current) return;
|
||||
const rect = containerRef.current.getBoundingClientRect();
|
||||
setCanvasSize({width: rect.width, height: rect.height});
|
||||
};
|
||||
|
||||
// 초기 크기 설정
|
||||
updateSize();
|
||||
|
||||
// ResizeObserver로 크기 변경 감지
|
||||
const resizeObserver = new ResizeObserver(updateSize);
|
||||
resizeObserver.observe(containerRef.current);
|
||||
|
||||
return () => {
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
}, []);
|
||||
const rect = containerRef.current.getBoundingClientRect();
|
||||
setCanvasSize({width: rect.width, height: rect.height});
|
||||
}, [width, height]);
|
||||
|
||||
// 선택된 영역 찾기
|
||||
const selectedArea = areas.find((a) => a.id === selectedAreaId);
|
||||
@ -345,8 +330,8 @@ export const EditorCanvas: React.FC<EditorCanvasProps> = ({
|
||||
ref={containerRef}
|
||||
className="editor-canvas"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
width,
|
||||
height,
|
||||
position: 'relative',
|
||||
cursor: showEditor ? getCursorStyle() : 'default',
|
||||
pointerEvents: showEditor ? 'auto' : 'none',
|
||||
|
||||
@ -13,13 +13,6 @@ const EASING_OPTIONS: { value: EasingFunction; label: string }[] = [
|
||||
{ value: 'easeInOut', label: '가감속 (Ease In Out)' },
|
||||
{ value: 'easeInQuad', label: '가속² (Ease In Quad)' },
|
||||
{ value: 'easeOutQuad', label: '감속² (Ease Out Quad)' },
|
||||
{ value: 'steps2', label: '2단계 스텝' },
|
||||
{ value: 'steps3', label: '3단계 스텝' },
|
||||
{ value: 'steps4', label: '4단계 스텝' },
|
||||
{ value: 'steps5', label: '5단계 스텝' },
|
||||
{ value: 'steps6', label: '6단계 스텝' },
|
||||
{ value: 'steps8', label: '8단계 스텝' },
|
||||
{ value: 'steps10', label: '10단계 스텝' },
|
||||
];
|
||||
|
||||
export const ParameterPanel: React.FC<ParameterPanelProps> = ({ area, onUpdateArea }) => {
|
||||
@ -91,22 +84,6 @@ export const ParameterPanel: React.FC<ParameterPanelProps> = ({ area, onUpdateAr
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* 렌즈 효과 */}
|
||||
<div className="parameter-group">
|
||||
<label>
|
||||
렌즈 효과: {((area.lensEffect?.strength ?? 0) > 0 ? '볼록 ' : (area.lensEffect?.strength ?? 0) < 0 ? '오목 ' : '')}{((area.lensEffect?.strength ?? 0) * 100).toFixed(0)}%
|
||||
</label>
|
||||
<input
|
||||
type="range"
|
||||
min="-1"
|
||||
max="1"
|
||||
step="0.01"
|
||||
value={area.lensEffect?.strength ?? 0}
|
||||
onChange={(e) => onUpdateArea({ lensEffect: { strength: parseFloat(e.target.value) } })}
|
||||
className="slider"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 포인트 좌표 (읽기 전용 표시) */}
|
||||
<div className="parameter-group">
|
||||
<label>포인트 좌표 (캔버스에서 드래그)</label>
|
||||
|
||||
@ -34,7 +34,6 @@ export class ThreeScene {
|
||||
u_numAreas: { value: 0 },
|
||||
u_dragVectors: { value: new Float32Array(16) }, // 8벡터 × 2(x,y)
|
||||
u_distortionStrengths: { value: new Float32Array(8) },
|
||||
u_lensEffects: { value: new Float32Array(8) },
|
||||
};
|
||||
|
||||
this.handleResize();
|
||||
|
||||
@ -4,7 +4,6 @@ uniform vec2 u_points[32]; // 최대 8영역 × 4포인트 (정규화된
|
||||
uniform int u_numAreas;
|
||||
uniform vec2 u_dragVectors[8]; // 드래그 벡터 (정규화된 좌표 0-1)
|
||||
uniform float u_distortionStrengths[8];
|
||||
uniform float u_lensEffects[8];
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
@ -75,15 +74,6 @@ void main() {
|
||||
// dragVector는 정규화된 좌표(0-1)이므로 바로 사용
|
||||
vec2 distortion = u_dragVectors[i] * influence * u_distortionStrengths[i];
|
||||
texCoord += distortion;
|
||||
|
||||
// 렌즈 왜곡 효과 (방사형 UV 왜곡)
|
||||
if (abs(u_lensEffects[i]) > 0.001) {
|
||||
vec2 centered = uv_local - vec2(0.5);
|
||||
float dist2 = dot(centered, centered);
|
||||
float lensK = u_lensEffects[i] * 2.0; // 강도 스케일링
|
||||
vec2 lensDistortion = centered * lensK * dist2;
|
||||
texCoord += lensDistortion * u_distortionStrengths[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,14 +17,7 @@ export type EasingFunction =
|
||||
| 'easeInQuad'
|
||||
| 'easeOutQuad'
|
||||
| 'easeInCubic'
|
||||
| 'easeOutCubic'
|
||||
| 'steps2'
|
||||
| 'steps3'
|
||||
| 'steps4'
|
||||
| 'steps5'
|
||||
| 'steps6'
|
||||
| 'steps8'
|
||||
| 'steps10';
|
||||
| 'easeOutCubic';
|
||||
|
||||
/**
|
||||
* 내장 모션 프리셋 타입
|
||||
@ -99,11 +92,6 @@ export interface DistortionArea {
|
||||
influenceRadius: number;
|
||||
maxStrength: number;
|
||||
};
|
||||
/** 렌즈 효과 설정 (선택사항) */
|
||||
lensEffect?: {
|
||||
/** 렌즈 강도 (양수: 볼록, 음수: 오목, 0: 없음, 범위: -1.0 ~ 1.0) */
|
||||
strength: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -17,8 +17,6 @@ export interface ShaderUniforms {
|
||||
u_dragVectors: THREE.IUniform<Float32Array>;
|
||||
/** 각 영역의 왜곡 강도 배열 */
|
||||
u_distortionStrengths: THREE.IUniform<Float32Array>;
|
||||
/** 각 영역의 렌즈 효과 강도 배열 */
|
||||
u_lensEffects: THREE.IUniform<Float32Array>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -10,8 +10,6 @@ export const SHADER_CONFIG = {
|
||||
MAX_DRAG_VECTORS: 8,
|
||||
/** 최대 강도 배열 크기 */
|
||||
MAX_STRENGTHS: 8,
|
||||
/** 최대 렌즈 효과 배열 크기 */
|
||||
MAX_LENS_EFFECTS: 8,
|
||||
} as const;
|
||||
|
||||
/**
|
||||
@ -38,6 +36,4 @@ export const DEFAULT_AREA = {
|
||||
VECTOR_A: { x: 0.1, y: 0.1 },
|
||||
/** 기본 벡터 B */
|
||||
VECTOR_B: { x: -0.1, y: -0.1 },
|
||||
/** 기본 렌즈 효과 강도 */
|
||||
LENS_STRENGTH: 0,
|
||||
} as const;
|
||||
@ -2,10 +2,6 @@ import { type EasingFunction } from '../types';
|
||||
|
||||
type EasingFunc = (t: number) => number;
|
||||
|
||||
/** 스텝 이징 헬퍼: floor(t * n) / n → n단계로 양자화 */
|
||||
const createStepEasing = (steps: number): EasingFunc =>
|
||||
(t) => Math.floor(t * steps) / steps;
|
||||
|
||||
/**
|
||||
* 이징 함수 구현 맵
|
||||
*/
|
||||
@ -21,14 +17,6 @@ const easingFunctions: Record<EasingFunction, EasingFunc> = {
|
||||
|
||||
easeInCubic: (t) => t * t * t,
|
||||
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
|
||||
|
||||
steps2: createStepEasing(2),
|
||||
steps3: createStepEasing(3),
|
||||
steps4: createStepEasing(4),
|
||||
steps5: createStepEasing(5),
|
||||
steps6: createStepEasing(6),
|
||||
steps8: createStepEasing(8),
|
||||
steps10: createStepEasing(10),
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user