125 lines
3.1 KiB
TypeScript
125 lines
3.1 KiB
TypeScript
export interface AccelerometerControllerCallbacks {
|
|
onSample: (x: number, y: number, z: number) => void
|
|
onError: (message: string) => void
|
|
}
|
|
|
|
const ACCELEROMETER_START_RETRY_DELAY_MS = 120
|
|
|
|
export class AccelerometerController {
|
|
callbacks: AccelerometerControllerCallbacks
|
|
listening: boolean
|
|
starting: boolean
|
|
accelerometerCallback: ((result: WechatMiniprogram.OnAccelerometerChangeCallbackResult) => void) | null
|
|
retryTimer: number
|
|
|
|
constructor(callbacks: AccelerometerControllerCallbacks) {
|
|
this.callbacks = callbacks
|
|
this.listening = false
|
|
this.starting = false
|
|
this.accelerometerCallback = null
|
|
this.retryTimer = 0
|
|
}
|
|
|
|
start(): void {
|
|
if (this.listening || this.starting) {
|
|
return
|
|
}
|
|
|
|
if (typeof wx.startAccelerometer !== 'function' || typeof wx.onAccelerometerChange !== 'function') {
|
|
this.callbacks.onError('当前环境不支持加速度计监听')
|
|
return
|
|
}
|
|
|
|
this.clearRetryTimer()
|
|
this.starting = true
|
|
this.detachCallback()
|
|
wx.stopAccelerometer({
|
|
complete: () => {
|
|
this.startAfterStop(false)
|
|
},
|
|
})
|
|
}
|
|
|
|
private startAfterStop(retried: boolean): void {
|
|
const callback = (result: WechatMiniprogram.OnAccelerometerChangeCallbackResult) => {
|
|
if (
|
|
typeof result.x !== 'number'
|
|
|| typeof result.y !== 'number'
|
|
|| typeof result.z !== 'number'
|
|
|| Number.isNaN(result.x)
|
|
|| Number.isNaN(result.y)
|
|
|| Number.isNaN(result.z)
|
|
) {
|
|
return
|
|
}
|
|
|
|
this.callbacks.onSample(result.x, result.y, result.z)
|
|
}
|
|
|
|
this.accelerometerCallback = callback
|
|
wx.onAccelerometerChange(callback)
|
|
wx.startAccelerometer({
|
|
interval: 'ui',
|
|
success: () => {
|
|
this.starting = false
|
|
this.listening = true
|
|
},
|
|
fail: (res) => {
|
|
const errorMessage = res && res.errMsg ? res.errMsg : 'startAccelerometer failed'
|
|
if (!retried && errorMessage.indexOf('has enable') >= 0) {
|
|
this.detachCallback()
|
|
this.clearRetryTimer()
|
|
this.retryTimer = setTimeout(() => {
|
|
this.retryTimer = 0
|
|
wx.stopAccelerometer({
|
|
complete: () => {
|
|
this.startAfterStop(true)
|
|
},
|
|
})
|
|
}, ACCELEROMETER_START_RETRY_DELAY_MS) as unknown as number
|
|
return
|
|
}
|
|
|
|
this.starting = false
|
|
this.detachCallback()
|
|
this.callbacks.onError(errorMessage)
|
|
},
|
|
})
|
|
}
|
|
|
|
stop(): void {
|
|
this.clearRetryTimer()
|
|
this.detachCallback()
|
|
wx.stopAccelerometer({
|
|
complete: () => {},
|
|
})
|
|
this.starting = false
|
|
this.listening = false
|
|
}
|
|
|
|
destroy(): void {
|
|
this.stop()
|
|
}
|
|
|
|
private clearRetryTimer(): void {
|
|
if (!this.retryTimer) {
|
|
return
|
|
}
|
|
|
|
clearTimeout(this.retryTimer)
|
|
this.retryTimer = 0
|
|
}
|
|
|
|
private detachCallback(): void {
|
|
if (!this.accelerometerCallback) {
|
|
return
|
|
}
|
|
|
|
if (typeof wx.offAccelerometerChange === 'function') {
|
|
wx.offAccelerometerChange(this.accelerometerCallback)
|
|
}
|
|
|
|
this.accelerometerCallback = null
|
|
}
|
|
}
|