fix: align mouse interaction toggling with other toggles

This commit is contained in:
Akatsh1
2025-12-24 14:45:08 +08:00
parent 6dabeae6be
commit 211f4bd703
3 changed files with 30 additions and 6 deletions

View File

@@ -43,6 +43,7 @@ export const MARBLE_CONFIG = {
repelRadius: 300, // Repulsion radius
repelForce: 400, // Repulsion force
attractForce: 600, // Attraction force
enable: true,
},
// Device motion interaction configuration
deviceOrientation: {

View File

@@ -19,6 +19,7 @@ export interface MarbleSystemConfig {
repelRadius?: number;
repelForce?: number;
attractForce?: number;
enable?: boolean;
};
deviceOrientationConfig?: {
sensitivity?: number;
@@ -36,9 +37,6 @@ export class MarbleSystem {
private container: HTMLElement;
private marbles: Marble[] = [];
// Mouse interaction enabled state
private mouseInteractionEnabled: boolean = true;
// Subsystems
private mouseInteraction: MouseInteraction;
private deviceOrientationInteraction: DeviceOrientationInteraction;
@@ -75,6 +73,9 @@ export class MarbleSystem {
attractForce:
config.mouseInteractionConfig?.attractForce ??
MARBLE_CONFIG.mouseInteraction.attractForce,
enable:
config.mouseInteractionConfig?.enable ??
MARBLE_CONFIG.mouseInteraction.enable,
};
this.mouseInteraction = new MouseInteraction(mouseConfig);
this.mouseInteraction.init();
@@ -176,7 +177,11 @@ export class MarbleSystem {
for (let i = 0; i < subSteps; i++) {
// Apply mouse force field
if (this.mouseInteractionEnabled) { //mouse-interaction-trigger controll
const mouseActive =
this.mouseInteraction.isActivated() &&
this.mouseInteraction.getEnabled();
if (mouseActive) {
for (const marble of this.marbles) {
if (this.mouseInteraction.shouldApplyForce(marble)) {
this.mouseInteraction.applyForce(marble, subDt);
@@ -363,7 +368,7 @@ export class MarbleSystem {
// Toggle mouse interaction
public setMouseInteraction(enabled: boolean): void {
this.mouseInteractionEnabled = enabled;
this.mouseInteraction.updateConfig({ enable: enabled });
}
// Toggle debug mode (show velocity vectors)

View File

@@ -16,6 +16,7 @@ export interface MouseInteractionConfig {
repelRadius: number; // Repulsion radius
repelForce: number; // Repulsion force
attractForce: number; // Attraction force
enable: boolean;
}
export class MouseInteraction {
@@ -24,6 +25,7 @@ export class MouseInteraction {
private isShiftPressed: boolean = false;
private lastMoveTime: number = 0;
private isMoving: boolean = false;
private isActive: boolean = false;
private config: MouseInteractionConfig;
constructor(config: MouseInteractionConfig) {
@@ -32,6 +34,8 @@ export class MouseInteraction {
// Initialize mouse interaction listeners
public init(): void {
if (typeof window === "undefined") return;
window.addEventListener("mousemove", (e) => {
this.mouseX = e.clientX;
this.mouseY = e.clientY;
@@ -61,10 +65,14 @@ export class MouseInteraction {
this.isShiftPressed = false;
}
});
this.isActive = true;
}
// Determine if force field should be applied to marble
public shouldApplyForce(marble: Marble): boolean {
if (!this.isActive || !this.config.enable) return false;
// Check if mouse moved recently (within 300ms)
const now = performance.now();
if (now - this.lastMoveTime > 300) {
@@ -96,11 +104,13 @@ export class MouseInteraction {
// Get whether force field is active
public isForceFieldActive(): boolean {
const now = performance.now();
return this.isMoving && now - this.lastMoveTime <= 300;
return this.config.enable && this.isMoving && now - this.lastMoveTime <= 300;
}
// Apply mouse force field effect (Note: This function should only be called when shouldApplyForce returns true)
public applyForce(marble: Marble, dt: number): void {
if (!this.isActive || !this.config.enable) return;
// Fix state at the start of function to avoid state change during execution
const isAttractMode = this.isShiftPressed;
const { attractRadius, repelRadius, repelForce, attractForce } =
@@ -145,4 +155,12 @@ export class MouseInteraction {
public isAttractMode(): boolean {
return this.isShiftPressed;
}
public getEnabled(): boolean {
return this.config.enable;
}
public isActivated(): boolean {
return this.isActive;
}
}