feat: Improve mouse interaction to affect multiple areas
- 마우스가 닿는 모든 영역에 왜곡 효과가 적용되도록 수정했습니다. - 기존에는 마우스가 처음 닿는 단일 영역에만 효과가 적용되었으나, 이제는 마우스 커서가 영역을 벗어나도 해당 영역에 대한 스프링 물리 효과가 유지되도록 변경되었습니다. - `useMouseInteraction` 훅에서 `interactingAreaIndex` 대신 `interactingAreaIndices` (Set)를 사용하여 여러 영역을 동시에 추적합니다. - 영역 진입 시 스프링이 리셋되고, 영역 이탈 시 평형 상태로 복귀하는 로직이 추가되었습니다.
This commit is contained in:
parent
7f6a72c058
commit
ddcf8b463a
2
dist/index.d.mts
vendored
2
dist/index.d.mts
vendored
@ -531,7 +531,7 @@ declare const useMouseVelocity: (containerRef: React.RefObject<HTMLElement | nul
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 마우스 인터랙션 기반 기존 영역 제어 훅
|
* 마우스 인터랙션 기반 기존 영역 제어 훅
|
||||||
* 기존 영역을 손으로 튕기는 효과
|
* 마우스가 지나가는 모든 영역에 효과 적용
|
||||||
*/
|
*/
|
||||||
declare const useMouseInteraction: (containerRef: React.RefObject<HTMLElement | null>, config: MouseInteractionConfig) => {
|
declare const useMouseInteraction: (containerRef: React.RefObject<HTMLElement | null>, config: MouseInteractionConfig) => {
|
||||||
updateInteraction: (areas: DistortionArea[], deltaTime: number) => DistortionArea[];
|
updateInteraction: (areas: DistortionArea[], deltaTime: number) => DistortionArea[];
|
||||||
|
|||||||
2
dist/index.d.ts
vendored
2
dist/index.d.ts
vendored
@ -531,7 +531,7 @@ declare const useMouseVelocity: (containerRef: React.RefObject<HTMLElement | nul
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 마우스 인터랙션 기반 기존 영역 제어 훅
|
* 마우스 인터랙션 기반 기존 영역 제어 훅
|
||||||
* 기존 영역을 손으로 튕기는 효과
|
* 마우스가 지나가는 모든 영역에 효과 적용
|
||||||
*/
|
*/
|
||||||
declare const useMouseInteraction: (containerRef: React.RefObject<HTMLElement | null>, config: MouseInteractionConfig) => {
|
declare const useMouseInteraction: (containerRef: React.RefObject<HTMLElement | null>, config: MouseInteractionConfig) => {
|
||||||
updateInteraction: (areas: DistortionArea[], deltaTime: number) => DistortionArea[];
|
updateInteraction: (areas: DistortionArea[], deltaTime: number) => DistortionArea[];
|
||||||
|
|||||||
38
dist/index.js
vendored
38
dist/index.js
vendored
@ -582,7 +582,7 @@ var isPointInPolygon = (point, polygon) => {
|
|||||||
};
|
};
|
||||||
var useMouseInteraction = (containerRef, config) => {
|
var useMouseInteraction = (containerRef, config) => {
|
||||||
const { getState } = useMouseVelocity(containerRef);
|
const { getState } = useMouseVelocity(containerRef);
|
||||||
const [interactingAreaIndex, setInteractingAreaIndex] = (0, import_react3.useState)(null);
|
const [interactingAreaIndices, setInteractingAreaIndices] = (0, import_react3.useState)(/* @__PURE__ */ new Set());
|
||||||
const springPhysicsMapRef = (0, import_react3.useRef)(/* @__PURE__ */ new Map());
|
const springPhysicsMapRef = (0, import_react3.useRef)(/* @__PURE__ */ new Map());
|
||||||
const getSpringPhysics = (0, import_react3.useCallback)((areaIndex) => {
|
const getSpringPhysics = (0, import_react3.useCallback)((areaIndex) => {
|
||||||
if (!springPhysicsMapRef.current.has(areaIndex)) {
|
if (!springPhysicsMapRef.current.has(areaIndex)) {
|
||||||
@ -594,24 +594,27 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
if (!config.enabled) return areas;
|
if (!config.enabled) return areas;
|
||||||
const mouseState = getState();
|
const mouseState = getState();
|
||||||
if (mouseState.isDragging && mouseState.position) {
|
if (mouseState.isDragging && mouseState.position) {
|
||||||
if (interactingAreaIndex === null) {
|
const currentlyInAreas = /* @__PURE__ */ new Set();
|
||||||
for (let i = areas.length - 1; i >= 0; i--) {
|
for (let i = 0; i < areas.length; i++) {
|
||||||
if (isPointInPolygon(mouseState.position, areas[i].basePoints)) {
|
if (isPointInPolygon(mouseState.position, areas[i].basePoints)) {
|
||||||
setInteractingAreaIndex(i);
|
currentlyInAreas.add(i);
|
||||||
|
if (!interactingAreaIndices.has(i)) {
|
||||||
getSpringPhysics(i).reset();
|
getSpringPhysics(i).reset();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (interactingAreaIndex !== null) {
|
interactingAreaIndices.forEach((areaIndex) => {
|
||||||
|
if (!currentlyInAreas.has(areaIndex)) {
|
||||||
|
getSpringPhysics(areaIndex).returnToEquilibrium();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setInteractingAreaIndices(currentlyInAreas);
|
||||||
const velocityMult = config.velocityMultiplier || 1;
|
const velocityMult = config.velocityMultiplier || 1;
|
||||||
const spring = getSpringPhysics(interactingAreaIndex);
|
|
||||||
const velocityMag = Math.sqrt(
|
const velocityMag = Math.sqrt(
|
||||||
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
||||||
);
|
);
|
||||||
const minVel = config.minVelocity || 0.05;
|
const minVel = config.minVelocity || 0.05;
|
||||||
const maxVel = config.maxVelocity || 5;
|
const maxVel = config.maxVelocity || 5;
|
||||||
if (velocityMag >= minVel) {
|
|
||||||
let clampedVelocity = mouseState.velocity;
|
let clampedVelocity = mouseState.velocity;
|
||||||
if (velocityMag > maxVel) {
|
if (velocityMag > maxVel) {
|
||||||
const scale = maxVel / velocityMag;
|
const scale = maxVel / velocityMag;
|
||||||
@ -620,15 +623,17 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
y: mouseState.velocity.y * scale
|
y: mouseState.velocity.y * scale
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
currentlyInAreas.forEach((areaIndex) => {
|
||||||
|
const spring = getSpringPhysics(areaIndex);
|
||||||
|
if (velocityMag >= minVel) {
|
||||||
spring.setTarget(clampedVelocity, velocityMult);
|
spring.setTarget(clampedVelocity, velocityMult);
|
||||||
} else {
|
} else {
|
||||||
spring.returnToEquilibrium();
|
spring.returnToEquilibrium();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
} else {
|
} else {
|
||||||
if (interactingAreaIndex !== null) {
|
if (interactingAreaIndices.size > 0) {
|
||||||
const velocityMult = config.velocityMultiplier || 1;
|
const velocityMult = config.velocityMultiplier || 1;
|
||||||
const spring = getSpringPhysics(interactingAreaIndex);
|
|
||||||
const maxVel = config.maxVelocity || 5;
|
const maxVel = config.maxVelocity || 5;
|
||||||
const velocityMag = Math.sqrt(
|
const velocityMag = Math.sqrt(
|
||||||
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
||||||
@ -641,8 +646,11 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
y: mouseState.velocity.y * scale
|
y: mouseState.velocity.y * scale
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
interactingAreaIndices.forEach((areaIndex) => {
|
||||||
|
const spring = getSpringPhysics(areaIndex);
|
||||||
spring.setInitialVelocity(clampedVelocity, velocityMult);
|
spring.setInitialVelocity(clampedVelocity, velocityMult);
|
||||||
setInteractingAreaIndex(null);
|
});
|
||||||
|
setInteractingAreaIndices(/* @__PURE__ */ new Set());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return areas.map((area, index) => {
|
return areas.map((area, index) => {
|
||||||
@ -651,7 +659,7 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
const springVelocity = spring.getVelocity();
|
const springVelocity = spring.getVelocity();
|
||||||
const springDisplacement = spring.getDisplacement();
|
const springDisplacement = spring.getDisplacement();
|
||||||
const isSpringActive = Math.sqrt(springVelocity.x ** 2 + springVelocity.y ** 2) > 1e-3 || Math.sqrt(springDisplacement.x ** 2 + springDisplacement.y ** 2) > 1e-3;
|
const isSpringActive = Math.sqrt(springVelocity.x ** 2 + springVelocity.y ** 2) > 1e-3 || Math.sqrt(springDisplacement.x ** 2 + springDisplacement.y ** 2) > 1e-3;
|
||||||
if (index !== interactingAreaIndex && !isSpringActive) {
|
if (!interactingAreaIndices.has(index) && !isSpringActive) {
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
const displacement = spring.update(deltaTime);
|
const displacement = spring.update(deltaTime);
|
||||||
@ -667,7 +675,7 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [config, getState, interactingAreaIndex, getSpringPhysics]);
|
}, [config, getState, interactingAreaIndices, getSpringPhysics]);
|
||||||
const updateConfig = (0, import_react3.useCallback)((newConfig) => {
|
const updateConfig = (0, import_react3.useCallback)((newConfig) => {
|
||||||
const physicsConfig = newConfig.physics;
|
const physicsConfig = newConfig.physics;
|
||||||
if (physicsConfig) {
|
if (physicsConfig) {
|
||||||
@ -680,7 +688,7 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
springPhysicsMapRef.current.forEach((spring) => {
|
springPhysicsMapRef.current.forEach((spring) => {
|
||||||
spring.reset();
|
spring.reset();
|
||||||
});
|
});
|
||||||
setInteractingAreaIndex(null);
|
setInteractingAreaIndices(/* @__PURE__ */ new Set());
|
||||||
}, []);
|
}, []);
|
||||||
return {
|
return {
|
||||||
updateInteraction,
|
updateInteraction,
|
||||||
|
|||||||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
38
dist/index.mjs
vendored
38
dist/index.mjs
vendored
@ -533,7 +533,7 @@ var isPointInPolygon = (point, polygon) => {
|
|||||||
};
|
};
|
||||||
var useMouseInteraction = (containerRef, config) => {
|
var useMouseInteraction = (containerRef, config) => {
|
||||||
const { getState } = useMouseVelocity(containerRef);
|
const { getState } = useMouseVelocity(containerRef);
|
||||||
const [interactingAreaIndex, setInteractingAreaIndex] = useState(null);
|
const [interactingAreaIndices, setInteractingAreaIndices] = useState(/* @__PURE__ */ new Set());
|
||||||
const springPhysicsMapRef = useRef3(/* @__PURE__ */ new Map());
|
const springPhysicsMapRef = useRef3(/* @__PURE__ */ new Map());
|
||||||
const getSpringPhysics = useCallback2((areaIndex) => {
|
const getSpringPhysics = useCallback2((areaIndex) => {
|
||||||
if (!springPhysicsMapRef.current.has(areaIndex)) {
|
if (!springPhysicsMapRef.current.has(areaIndex)) {
|
||||||
@ -545,24 +545,27 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
if (!config.enabled) return areas;
|
if (!config.enabled) return areas;
|
||||||
const mouseState = getState();
|
const mouseState = getState();
|
||||||
if (mouseState.isDragging && mouseState.position) {
|
if (mouseState.isDragging && mouseState.position) {
|
||||||
if (interactingAreaIndex === null) {
|
const currentlyInAreas = /* @__PURE__ */ new Set();
|
||||||
for (let i = areas.length - 1; i >= 0; i--) {
|
for (let i = 0; i < areas.length; i++) {
|
||||||
if (isPointInPolygon(mouseState.position, areas[i].basePoints)) {
|
if (isPointInPolygon(mouseState.position, areas[i].basePoints)) {
|
||||||
setInteractingAreaIndex(i);
|
currentlyInAreas.add(i);
|
||||||
|
if (!interactingAreaIndices.has(i)) {
|
||||||
getSpringPhysics(i).reset();
|
getSpringPhysics(i).reset();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (interactingAreaIndex !== null) {
|
interactingAreaIndices.forEach((areaIndex) => {
|
||||||
|
if (!currentlyInAreas.has(areaIndex)) {
|
||||||
|
getSpringPhysics(areaIndex).returnToEquilibrium();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setInteractingAreaIndices(currentlyInAreas);
|
||||||
const velocityMult = config.velocityMultiplier || 1;
|
const velocityMult = config.velocityMultiplier || 1;
|
||||||
const spring = getSpringPhysics(interactingAreaIndex);
|
|
||||||
const velocityMag = Math.sqrt(
|
const velocityMag = Math.sqrt(
|
||||||
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
||||||
);
|
);
|
||||||
const minVel = config.minVelocity || 0.05;
|
const minVel = config.minVelocity || 0.05;
|
||||||
const maxVel = config.maxVelocity || 5;
|
const maxVel = config.maxVelocity || 5;
|
||||||
if (velocityMag >= minVel) {
|
|
||||||
let clampedVelocity = mouseState.velocity;
|
let clampedVelocity = mouseState.velocity;
|
||||||
if (velocityMag > maxVel) {
|
if (velocityMag > maxVel) {
|
||||||
const scale = maxVel / velocityMag;
|
const scale = maxVel / velocityMag;
|
||||||
@ -571,15 +574,17 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
y: mouseState.velocity.y * scale
|
y: mouseState.velocity.y * scale
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
currentlyInAreas.forEach((areaIndex) => {
|
||||||
|
const spring = getSpringPhysics(areaIndex);
|
||||||
|
if (velocityMag >= minVel) {
|
||||||
spring.setTarget(clampedVelocity, velocityMult);
|
spring.setTarget(clampedVelocity, velocityMult);
|
||||||
} else {
|
} else {
|
||||||
spring.returnToEquilibrium();
|
spring.returnToEquilibrium();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
} else {
|
} else {
|
||||||
if (interactingAreaIndex !== null) {
|
if (interactingAreaIndices.size > 0) {
|
||||||
const velocityMult = config.velocityMultiplier || 1;
|
const velocityMult = config.velocityMultiplier || 1;
|
||||||
const spring = getSpringPhysics(interactingAreaIndex);
|
|
||||||
const maxVel = config.maxVelocity || 5;
|
const maxVel = config.maxVelocity || 5;
|
||||||
const velocityMag = Math.sqrt(
|
const velocityMag = Math.sqrt(
|
||||||
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
||||||
@ -592,8 +597,11 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
y: mouseState.velocity.y * scale
|
y: mouseState.velocity.y * scale
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
interactingAreaIndices.forEach((areaIndex) => {
|
||||||
|
const spring = getSpringPhysics(areaIndex);
|
||||||
spring.setInitialVelocity(clampedVelocity, velocityMult);
|
spring.setInitialVelocity(clampedVelocity, velocityMult);
|
||||||
setInteractingAreaIndex(null);
|
});
|
||||||
|
setInteractingAreaIndices(/* @__PURE__ */ new Set());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return areas.map((area, index) => {
|
return areas.map((area, index) => {
|
||||||
@ -602,7 +610,7 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
const springVelocity = spring.getVelocity();
|
const springVelocity = spring.getVelocity();
|
||||||
const springDisplacement = spring.getDisplacement();
|
const springDisplacement = spring.getDisplacement();
|
||||||
const isSpringActive = Math.sqrt(springVelocity.x ** 2 + springVelocity.y ** 2) > 1e-3 || Math.sqrt(springDisplacement.x ** 2 + springDisplacement.y ** 2) > 1e-3;
|
const isSpringActive = Math.sqrt(springVelocity.x ** 2 + springVelocity.y ** 2) > 1e-3 || Math.sqrt(springDisplacement.x ** 2 + springDisplacement.y ** 2) > 1e-3;
|
||||||
if (index !== interactingAreaIndex && !isSpringActive) {
|
if (!interactingAreaIndices.has(index) && !isSpringActive) {
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
const displacement = spring.update(deltaTime);
|
const displacement = spring.update(deltaTime);
|
||||||
@ -618,7 +626,7 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [config, getState, interactingAreaIndex, getSpringPhysics]);
|
}, [config, getState, interactingAreaIndices, getSpringPhysics]);
|
||||||
const updateConfig = useCallback2((newConfig) => {
|
const updateConfig = useCallback2((newConfig) => {
|
||||||
const physicsConfig = newConfig.physics;
|
const physicsConfig = newConfig.physics;
|
||||||
if (physicsConfig) {
|
if (physicsConfig) {
|
||||||
@ -631,7 +639,7 @@ var useMouseInteraction = (containerRef, config) => {
|
|||||||
springPhysicsMapRef.current.forEach((spring) => {
|
springPhysicsMapRef.current.forEach((spring) => {
|
||||||
spring.reset();
|
spring.reset();
|
||||||
});
|
});
|
||||||
setInteractingAreaIndex(null);
|
setInteractingAreaIndices(/* @__PURE__ */ new Set());
|
||||||
}, []);
|
}, []);
|
||||||
return {
|
return {
|
||||||
updateInteraction,
|
updateInteraction,
|
||||||
|
|||||||
2
dist/index.mjs.map
vendored
2
dist/index.mjs.map
vendored
File diff suppressed because one or more lines are too long
@ -21,14 +21,14 @@ const isPointInPolygon = (point: Point, polygon: Point[]): boolean => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 마우스 인터랙션 기반 기존 영역 제어 훅
|
* 마우스 인터랙션 기반 기존 영역 제어 훅
|
||||||
* 기존 영역을 손으로 튕기는 효과
|
* 마우스가 지나가는 모든 영역에 효과 적용
|
||||||
*/
|
*/
|
||||||
export const useMouseInteraction = (
|
export const useMouseInteraction = (
|
||||||
containerRef: React.RefObject<HTMLElement | null>,
|
containerRef: React.RefObject<HTMLElement | null>,
|
||||||
config: MouseInteractionConfig
|
config: MouseInteractionConfig
|
||||||
) => {
|
) => {
|
||||||
const { getState } = useMouseVelocity(containerRef);
|
const { getState } = useMouseVelocity(containerRef);
|
||||||
const [interactingAreaIndex, setInteractingAreaIndex] = useState<number | null>(null);
|
const [interactingAreaIndices, setInteractingAreaIndices] = useState<Set<number>>(new Set());
|
||||||
const springPhysicsMapRef = useRef<Map<number, SpringPhysics>>(new Map());
|
const springPhysicsMapRef = useRef<Map<number, SpringPhysics>>(new Map());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,33 +51,38 @@ export const useMouseInteraction = (
|
|||||||
|
|
||||||
// 마우스 클릭/드래그 중이고 위치가 있으면
|
// 마우스 클릭/드래그 중이고 위치가 있으면
|
||||||
if (mouseState.isDragging && mouseState.position) {
|
if (mouseState.isDragging && mouseState.position) {
|
||||||
// 아직 영역을 선택하지 않았으면 찾기
|
// 현재 마우스 위치가 포함된 모든 영역 찾기
|
||||||
if (interactingAreaIndex === null) {
|
const currentlyInAreas = new Set<number>();
|
||||||
// 마우스 위치가 포함된 영역 찾기 (마지막 영역부터 - 위에 있는 영역 우선)
|
for (let i = 0; i < areas.length; i++) {
|
||||||
for (let i = areas.length - 1; i >= 0; i--) {
|
|
||||||
if (isPointInPolygon(mouseState.position, areas[i].basePoints)) {
|
if (isPointInPolygon(mouseState.position, areas[i].basePoints)) {
|
||||||
setInteractingAreaIndex(i);
|
currentlyInAreas.add(i);
|
||||||
// 해당 영역의 스프링 리셋
|
|
||||||
|
// 새로 진입한 영역이면 스프링 리셋
|
||||||
|
if (!interactingAreaIndices.has(i)) {
|
||||||
getSpringPhysics(i).reset();
|
getSpringPhysics(i).reset();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 드래그 중인 영역이 있으면 마우스 방향으로 실시간 늘어남
|
// 이전에 인터랙션하던 영역에서 벗어났으면 평형으로 복귀
|
||||||
if (interactingAreaIndex !== null) {
|
interactingAreaIndices.forEach((areaIndex) => {
|
||||||
|
if (!currentlyInAreas.has(areaIndex)) {
|
||||||
|
getSpringPhysics(areaIndex).returnToEquilibrium();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 인터랙션 영역 업데이트
|
||||||
|
setInteractingAreaIndices(currentlyInAreas);
|
||||||
|
|
||||||
|
// 현재 위치의 모든 영역에 속도 적용
|
||||||
const velocityMult = config.velocityMultiplier || 1.0;
|
const velocityMult = config.velocityMultiplier || 1.0;
|
||||||
const spring = getSpringPhysics(interactingAreaIndex);
|
|
||||||
|
|
||||||
// 속도 크기 확인
|
|
||||||
const velocityMag = Math.sqrt(
|
const velocityMag = Math.sqrt(
|
||||||
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
||||||
);
|
);
|
||||||
const minVel = config.minVelocity || 0.05;
|
const minVel = config.minVelocity || 0.05;
|
||||||
const maxVel = config.maxVelocity || 5.0;
|
const maxVel = config.maxVelocity || 5.0;
|
||||||
|
|
||||||
if (velocityMag >= minVel) {
|
// 속도 클램핑
|
||||||
// 속도 클램핑 (너무 빠른 움직임 제한)
|
|
||||||
let clampedVelocity = mouseState.velocity;
|
let clampedVelocity = mouseState.velocity;
|
||||||
if (velocityMag > maxVel) {
|
if (velocityMag > maxVel) {
|
||||||
const scale = maxVel / velocityMag;
|
const scale = maxVel / velocityMag;
|
||||||
@ -87,21 +92,24 @@ export const useMouseInteraction = (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 드래그 중: 클램핑된 마우스 속도를 목표로 설정
|
currentlyInAreas.forEach((areaIndex) => {
|
||||||
|
const spring = getSpringPhysics(areaIndex);
|
||||||
|
|
||||||
|
if (velocityMag >= minVel) {
|
||||||
|
// 드래그 중: 마우스 속도를 목표로 설정
|
||||||
spring.setTarget(clampedVelocity, velocityMult);
|
spring.setTarget(clampedVelocity, velocityMult);
|
||||||
} else {
|
} else {
|
||||||
// 드래그 중이지만 마우스가 멈춰있으면 평형으로 복귀
|
// 드래그 중이지만 마우스가 멈춰있으면 평형으로 복귀
|
||||||
spring.returnToEquilibrium();
|
spring.returnToEquilibrium();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
} else {
|
} else {
|
||||||
// 마우스를 놓았으면 마지막 속도를 초기 속도로 설정하여 튕김
|
// 마우스를 놓았으면 인터랙션 중이던 모든 영역에 튕김 효과
|
||||||
if (interactingAreaIndex !== null) {
|
if (interactingAreaIndices.size > 0) {
|
||||||
const velocityMult = config.velocityMultiplier || 1.0;
|
const velocityMult = config.velocityMultiplier || 1.0;
|
||||||
const spring = getSpringPhysics(interactingAreaIndex);
|
|
||||||
const maxVel = config.maxVelocity || 5.0;
|
const maxVel = config.maxVelocity || 5.0;
|
||||||
|
|
||||||
// 속도 클램핑 (놓을 때도 제한)
|
// 속도 클램핑
|
||||||
const velocityMag = Math.sqrt(
|
const velocityMag = Math.sqrt(
|
||||||
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
mouseState.velocity.x ** 2 + mouseState.velocity.y ** 2
|
||||||
);
|
);
|
||||||
@ -114,9 +122,13 @@ export const useMouseInteraction = (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 클램핑된 속도를 초기 속도로 설정하여 튕김
|
// 모든 인터랙션 영역에 초기 속도 설정
|
||||||
|
interactingAreaIndices.forEach((areaIndex) => {
|
||||||
|
const spring = getSpringPhysics(areaIndex);
|
||||||
spring.setInitialVelocity(clampedVelocity, velocityMult);
|
spring.setInitialVelocity(clampedVelocity, velocityMult);
|
||||||
setInteractingAreaIndex(null);
|
});
|
||||||
|
|
||||||
|
setInteractingAreaIndices(new Set());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +144,7 @@ export const useMouseInteraction = (
|
|||||||
Math.sqrt(springDisplacement.x ** 2 + springDisplacement.y ** 2) > 0.001;
|
Math.sqrt(springDisplacement.x ** 2 + springDisplacement.y ** 2) > 0.001;
|
||||||
|
|
||||||
// 드래그 중이 아니고 스프링도 비활성이면 업데이트 안 함
|
// 드래그 중이 아니고 스프링도 비활성이면 업데이트 안 함
|
||||||
if (index !== interactingAreaIndex && !isSpringActive) {
|
if (!interactingAreaIndices.has(index) && !isSpringActive) {
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +169,7 @@ export const useMouseInteraction = (
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [config, getState, interactingAreaIndex, getSpringPhysics]);
|
}, [config, getState, interactingAreaIndices, getSpringPhysics]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 물리 파라미터 업데이트
|
* 물리 파라미터 업데이트
|
||||||
@ -179,7 +191,7 @@ export const useMouseInteraction = (
|
|||||||
springPhysicsMapRef.current.forEach((spring) => {
|
springPhysicsMapRef.current.forEach((spring) => {
|
||||||
spring.reset();
|
spring.reset();
|
||||||
});
|
});
|
||||||
setInteractingAreaIndex(null);
|
setInteractingAreaIndices(new Set());
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user