优化指北针持续追踪手感
This commit is contained in:
@@ -57,6 +57,8 @@ const AUTO_ROTATE_SNAP_DEG = 0.1
|
||||
const AUTO_ROTATE_DEADZONE_DEG = 4
|
||||
const AUTO_ROTATE_MAX_STEP_DEG = 0.75
|
||||
const AUTO_ROTATE_HEADING_SMOOTHING = 0.46
|
||||
const COMPASS_NEEDLE_FRAME_MS = 16
|
||||
const COMPASS_NEEDLE_SNAP_DEG = 0.08
|
||||
const COMPASS_TUNING_PRESETS: Record<CompassTuningProfile, {
|
||||
needleMinSmoothing: number
|
||||
needleMaxSmoothing: number
|
||||
@@ -827,6 +829,7 @@ export class MapEngine {
|
||||
previewResetTimer: number
|
||||
viewSyncTimer: number
|
||||
autoRotateTimer: number
|
||||
compassNeedleTimer: number
|
||||
pendingViewPatch: Partial<MapEngineViewState>
|
||||
mounted: boolean
|
||||
diagnosticUiEnabled: boolean
|
||||
@@ -834,6 +837,7 @@ export class MapEngine {
|
||||
sensorHeadingDeg: number | null
|
||||
smoothedSensorHeadingDeg: number | null
|
||||
compassDisplayHeadingDeg: number | null
|
||||
targetCompassDisplayHeadingDeg: number | null
|
||||
compassSource: 'compass' | 'motion' | null
|
||||
compassTuningProfile: CompassTuningProfile
|
||||
smoothedMovementHeadingDeg: number | null
|
||||
@@ -1277,6 +1281,7 @@ export class MapEngine {
|
||||
this.previewResetTimer = 0
|
||||
this.viewSyncTimer = 0
|
||||
this.autoRotateTimer = 0
|
||||
this.compassNeedleTimer = 0
|
||||
this.pendingViewPatch = {}
|
||||
this.mounted = false
|
||||
this.diagnosticUiEnabled = false
|
||||
@@ -1284,6 +1289,7 @@ export class MapEngine {
|
||||
this.sensorHeadingDeg = null
|
||||
this.smoothedSensorHeadingDeg = null
|
||||
this.compassDisplayHeadingDeg = null
|
||||
this.targetCompassDisplayHeadingDeg = null
|
||||
this.compassSource = null
|
||||
this.compassTuningProfile = 'balanced'
|
||||
this.smoothedMovementHeadingDeg = null
|
||||
@@ -1399,6 +1405,7 @@ export class MapEngine {
|
||||
this.clearPreviewResetTimer()
|
||||
this.clearViewSyncTimer()
|
||||
this.clearAutoRotateTimer()
|
||||
this.clearCompassNeedleTimer()
|
||||
this.clearPunchFeedbackTimer()
|
||||
this.clearContentCardTimer()
|
||||
this.clearMapPulseTimer()
|
||||
@@ -2940,27 +2947,19 @@ export class MapEngine {
|
||||
const compassHeadingDeg = getCompassReferenceHeadingDeg(this.northReferenceMode, this.smoothedSensorHeadingDeg)
|
||||
if (this.compassDisplayHeadingDeg === null) {
|
||||
this.compassDisplayHeadingDeg = compassHeadingDeg
|
||||
this.targetCompassDisplayHeadingDeg = compassHeadingDeg
|
||||
this.syncCompassDisplayState()
|
||||
} else {
|
||||
this.targetCompassDisplayHeadingDeg = compassHeadingDeg
|
||||
const displayDeltaDeg = Math.abs(normalizeAngleDeltaDeg(compassHeadingDeg - this.compassDisplayHeadingDeg))
|
||||
if (displayDeltaDeg >= COMPASS_TUNING_PRESETS[this.compassTuningProfile].displayDeadzoneDeg) {
|
||||
this.compassDisplayHeadingDeg = interpolateAngleDeg(
|
||||
this.compassDisplayHeadingDeg,
|
||||
compassHeadingDeg,
|
||||
getCompassNeedleSmoothingFactor(
|
||||
this.compassDisplayHeadingDeg,
|
||||
compassHeadingDeg,
|
||||
this.compassTuningProfile,
|
||||
),
|
||||
)
|
||||
this.scheduleCompassNeedleFollow()
|
||||
}
|
||||
}
|
||||
|
||||
this.autoRotateHeadingDeg = this.resolveAutoRotateInputHeadingDeg()
|
||||
|
||||
this.setState({
|
||||
compassNeedleDeg: formatCompassNeedleDegForMode(this.northReferenceMode, this.compassDisplayHeadingDeg),
|
||||
sensorHeadingText: formatHeadingText(this.compassDisplayHeadingDeg),
|
||||
compassDeclinationText: formatCompassDeclinationText(this.northReferenceMode),
|
||||
compassSourceText: formatCompassSourceText(this.compassSource),
|
||||
...(this.diagnosticUiEnabled
|
||||
? {
|
||||
...this.getTelemetrySensorViewPatch(),
|
||||
@@ -2986,9 +2985,11 @@ export class MapEngine {
|
||||
|
||||
handleCompassError(message: string): void {
|
||||
this.clearAutoRotateTimer()
|
||||
this.clearCompassNeedleTimer()
|
||||
this.targetAutoRotationDeg = null
|
||||
this.autoRotateCalibrationPending = false
|
||||
this.compassSource = null
|
||||
this.targetCompassDisplayHeadingDeg = null
|
||||
this.setState({
|
||||
compassSourceText: formatCompassSourceText(null),
|
||||
autoRotateCalibrationText: formatAutoRotateCalibrationText(false, this.autoRotateCalibrationOffsetDeg),
|
||||
@@ -3013,6 +3014,7 @@ export class MapEngine {
|
||||
this.northReferenceMode = nextMode
|
||||
this.autoRotateCalibrationOffsetDeg = nextMapNorthOffsetDeg
|
||||
this.compassDisplayHeadingDeg = compassHeadingDeg
|
||||
this.targetCompassDisplayHeadingDeg = compassHeadingDeg
|
||||
|
||||
if (this.state.orientationMode === 'north-up') {
|
||||
const exactCenter = this.getExactCenterFromTranslate(this.state.tileTranslateX, this.state.tileTranslateY)
|
||||
@@ -3056,6 +3058,10 @@ export class MapEngine {
|
||||
if (this.state.orientationMode === 'heading-up' && this.refreshAutoRotateTarget()) {
|
||||
this.scheduleAutoRotate()
|
||||
}
|
||||
|
||||
if (this.compassDisplayHeadingDeg !== null) {
|
||||
this.syncCompassDisplayState()
|
||||
}
|
||||
}
|
||||
|
||||
setCourseHeading(headingDeg: number | null): void {
|
||||
@@ -3570,6 +3576,78 @@ export class MapEngine {
|
||||
this.autoRotateTimer = 0
|
||||
}
|
||||
}
|
||||
|
||||
clearCompassNeedleTimer(): void {
|
||||
if (this.compassNeedleTimer) {
|
||||
clearTimeout(this.compassNeedleTimer)
|
||||
this.compassNeedleTimer = 0
|
||||
}
|
||||
}
|
||||
|
||||
syncCompassDisplayState(): void {
|
||||
this.setState({
|
||||
compassNeedleDeg: formatCompassNeedleDegForMode(this.northReferenceMode, this.compassDisplayHeadingDeg),
|
||||
sensorHeadingText: formatHeadingText(this.compassDisplayHeadingDeg),
|
||||
compassDeclinationText: formatCompassDeclinationText(this.northReferenceMode),
|
||||
...(this.diagnosticUiEnabled
|
||||
? {
|
||||
...this.getTelemetrySensorViewPatch(),
|
||||
northReferenceButtonText: formatNorthReferenceButtonText(this.northReferenceMode),
|
||||
autoRotateSourceText: this.getAutoRotateSourceText(),
|
||||
northReferenceText: formatNorthReferenceText(this.northReferenceMode),
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
}
|
||||
|
||||
scheduleCompassNeedleFollow(): void {
|
||||
if (
|
||||
this.compassNeedleTimer
|
||||
|| this.targetCompassDisplayHeadingDeg === null
|
||||
|| this.compassDisplayHeadingDeg === null
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const step = () => {
|
||||
this.compassNeedleTimer = 0
|
||||
|
||||
if (
|
||||
this.targetCompassDisplayHeadingDeg === null
|
||||
|| this.compassDisplayHeadingDeg === null
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const deltaDeg = normalizeAngleDeltaDeg(
|
||||
this.targetCompassDisplayHeadingDeg - this.compassDisplayHeadingDeg,
|
||||
)
|
||||
const absDeltaDeg = Math.abs(deltaDeg)
|
||||
|
||||
if (absDeltaDeg <= COMPASS_NEEDLE_SNAP_DEG) {
|
||||
if (absDeltaDeg > 0.001) {
|
||||
this.compassDisplayHeadingDeg = this.targetCompassDisplayHeadingDeg
|
||||
this.syncCompassDisplayState()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
this.compassDisplayHeadingDeg = interpolateAngleDeg(
|
||||
this.compassDisplayHeadingDeg,
|
||||
this.targetCompassDisplayHeadingDeg,
|
||||
getCompassNeedleSmoothingFactor(
|
||||
this.compassDisplayHeadingDeg,
|
||||
this.targetCompassDisplayHeadingDeg,
|
||||
this.compassTuningProfile,
|
||||
),
|
||||
)
|
||||
this.syncCompassDisplayState()
|
||||
this.scheduleCompassNeedleFollow()
|
||||
}
|
||||
|
||||
this.compassNeedleTimer = setTimeout(step, COMPASS_NEEDLE_FRAME_MS) as unknown as number
|
||||
}
|
||||
|
||||
pickViewPatch(patch: Partial<MapEngineViewState>): Partial<MapEngineViewState> {
|
||||
const viewPatch = {} as Partial<MapEngineViewState>
|
||||
for (const key of VIEW_SYNC_KEYS) {
|
||||
|
||||
Reference in New Issue
Block a user