first commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
export class GyroController {
|
||||
private enabled = false;
|
||||
private pending = false;
|
||||
private generation = 0;
|
||||
private hasReading = false;
|
||||
private base: { beta: number; gamma: number } | null = null;
|
||||
constructor(private readonly setView: (x: number, y: number) => void, private readonly status: (message: string) => void) {}
|
||||
async toggle(): Promise<boolean> {
|
||||
if (this.enabled || this.pending) { this.dispose(); return false; }
|
||||
if (!window.isSecureContext || !('DeviceOrientationEvent' in window)) { this.status('자이로스코프를 사용할 수 없습니다.'); return false; }
|
||||
const generation = ++this.generation; this.pending = true;
|
||||
try {
|
||||
const device = window.DeviceOrientationEvent as typeof DeviceOrientationEvent & { requestPermission?: () => Promise<string> };
|
||||
this.status('센서 권한을 기다리는 중…');
|
||||
if (device.requestPermission && await device.requestPermission() !== 'granted') throw new Error('권한 거절됨');
|
||||
if (generation !== this.generation) return false;
|
||||
this.base = null; this.hasReading = false; this.pending = false; this.enabled = true; window.addEventListener('deviceorientation', this.onOrientation); this.status('센서값을 기다리는 중…'); return true;
|
||||
} catch (error) { this.pending = false; if (generation === this.generation) this.status(`자이로스코프를 사용할 수 없습니다 (${(error as Error).message})`); return false; }
|
||||
}
|
||||
reset(): void { this.base = null; }
|
||||
dispose(): void { ++this.generation; this.pending = false; this.enabled = false; this.base = null; window.removeEventListener('deviceorientation', this.onOrientation); }
|
||||
private onOrientation = (event: DeviceOrientationEvent): void => {
|
||||
if (!this.enabled || event.beta == null || event.gamma == null) return;
|
||||
if (!this.base) this.base = { beta: event.beta, gamma: event.gamma };
|
||||
const angle = (screen.orientation?.angle ?? 0) * Math.PI / 180;
|
||||
const x = event.gamma - this.base.gamma; const y = event.beta - this.base.beta;
|
||||
this.setView((x * Math.cos(angle) + y * Math.sin(angle)) / 35, (y * Math.cos(angle) - x * Math.sin(angle)) / 35); if (!this.hasReading) { this.hasReading = true; this.status('자이로스코프 활성'); }
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user