调整模型位置
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-10 13:09:04 +08:00
parent 626011bd6d
commit 3a8afa8d93

View File

@@ -133,6 +133,14 @@ const SGS_VISUAL_RENDER_CONFIG = {
}
} as const
const OVERVIEW_INITIAL_CAMERA_PARAMS = {
position: new THREE.Vector3(496.3356, 708.6058, 137.501),
target: new THREE.Vector3(-4.1432, -31.3659, 3.3982),
zoom: 1
} as const
const MODEL_ADJUST_IDLE_REPORT_DELAY_MS = 800
const degToRad = (degrees: number) => THREE.MathUtils.degToRad(degrees)
const INTERACTION_POLICY = {
@@ -347,14 +355,14 @@ const isLoading = ref(true)
const loadError = ref(false)
const loadingProgress = ref(0)
const loadingMessage = ref('正在读取馆内导览资源...')
const activeView = ref<ViewMode>(props.initialView)
const currentFloor = ref(props.initialFloorId)
const loadingDisplayMessage = '正在加载馆内三维场景'
const modelLoadErrorTitle = '馆内三维场景加载失败'
const modelLoadErrorMessage = '可能是网络原因,请重新加载。'
const setFriendlyModelLoadError = () => {
setProgress(0, modelLoadErrorMessage)
}
const activeView = ref<ViewMode>(props.initialView)
const currentFloor = ref(props.initialFloorId)
const selectedPOI = ref<RenderPoi | null>(null)
const activeFocusPoiId = ref('')
const floorIndex = ref<FloorIndexItem[]>([])
@@ -428,6 +436,8 @@ let floorExitZoomOutAccumulatedRatio = 0
let autoSwitchTemporarilyDisabled = false
let autoSwitchDisableTimer: ReturnType<typeof setTimeout> | null = null
let overviewEntryIntentStartedAt = 0
let modelAdjustReportTimer: ReturnType<typeof setTimeout> | null = null
let hasPendingManualModelAdjustment = false
let overviewEntryStartDistance = 0
let overviewEntryZoomInRounds = 0
let overviewWheelZoomInRounds = 0
@@ -539,6 +549,57 @@ const logThreeMapDiagnostic = (
console.debug(`[ThreeMap] ${event} ${stringifyDiagnosticPayload(payload)}`)
}
const roundModelAdjustValue = (value: number) => Number(value.toFixed(4))
const serializeVector3 = (value: THREE.Vector3) => ({
x: roundModelAdjustValue(value.x),
y: roundModelAdjustValue(value.y),
z: roundModelAdjustValue(value.z)
})
const serializeEulerDegrees = (value: THREE.Euler) => ({
x: roundModelAdjustValue(THREE.MathUtils.radToDeg(value.x)),
y: roundModelAdjustValue(THREE.MathUtils.radToDeg(value.y)),
z: roundModelAdjustValue(THREE.MathUtils.radToDeg(value.z))
})
const clearModelAdjustReportTimer = () => {
if (!modelAdjustReportTimer) return
clearTimeout(modelAdjustReportTimer)
modelAdjustReportTimer = null
}
const emitModelAdjustIdleReport = () => {
modelAdjustReportTimer = null
if (!hasPendingManualModelAdjustment || !camera || !controls || !activeModel) return
hasPendingManualModelAdjustment = false
const payload = {
view: activeView.value,
floorId: currentFloor.value,
modelName: activeModel.name || 'unnamed-model',
model: {
position: serializeVector3(activeModel.position),
rotationDeg: serializeEulerDegrees(activeModel.rotation),
scale: serializeVector3(activeModel.scale)
},
camera: {
position: serializeVector3(camera.position),
target: serializeVector3(controls.target),
distance: roundModelAdjustValue(controls.getDistance()),
zoom: roundModelAdjustValue(camera.zoom)
}
}
console.info('[ThreeMap] 模型停止移动,当前调参信息:', payload)
}
const scheduleModelAdjustIdleReport = () => {
if (!hasPendingManualModelAdjustment || isProgrammaticCameraChange || !camera || !controls || !activeModel) return
clearModelAdjustReportTimer()
modelAdjustReportTimer = window.setTimeout(emitModelAdjustIdleReport, MODEL_ADJUST_IDLE_REPORT_DELAY_MS)
}
const getInteractionPolicyMode = (): InteractionPolicyMode => (
activeView.value === 'overview' ? 'display' : 'explore'
)
@@ -572,11 +633,12 @@ const shouldEnableRotation = () => (
const shouldUseDirectMouseRotate = (event?: PointerEvent) => {
const hasAlt = event?.altKey ?? desktopRotateModifiers.alt
const hasShiftCtrlOrMeta = event
? event.shiftKey || event.ctrlKey || event.metaKey
: desktopRotateModifiers.shift || desktopRotateModifiers.ctrl || desktopRotateModifiers.meta
const hasCtrlOrMeta = event
? event.ctrlKey || event.metaKey
: desktopRotateModifiers.ctrl || desktopRotateModifiers.meta
const hasShift = event?.shiftKey ?? desktopRotateModifiers.shift
return hasAlt && !hasShiftCtrlOrMeta
return (hasCtrlOrMeta || hasAlt) && !hasShift
}
const resetInteractionGateState = () => {
@@ -600,6 +662,7 @@ const syncControlInteractionOptions = (event?: PointerEvent) => {
const policy = INTERACTION_POLICY[getInteractionPolicyMode()]
const enableRotate = shouldEnableRotation()
const enablePan = policy.allowPan && !enableRotate
const directMouseRotate = enableRotate && shouldUseDirectMouseRotate(event)
controls.enableRotate = enableRotate
controls.enablePan = enablePan
@@ -612,14 +675,18 @@ const syncControlInteractionOptions = (event?: PointerEvent) => {
controls.maxAzimuthAngle = policy.maxAzimuthAngle
controls.mouseButtons.LEFT = enableRotate
? shouldUseDirectMouseRotate(event)
? directMouseRotate
? THREE.MOUSE.ROTATE
: THREE.MOUSE.PAN
: enablePan
? THREE.MOUSE.PAN
: null
controls.mouseButtons.MIDDLE = THREE.MOUSE.DOLLY
controls.mouseButtons.RIGHT = enablePan ? THREE.MOUSE.PAN : null
controls.mouseButtons.RIGHT = directMouseRotate
? THREE.MOUSE.ROTATE
: enablePan
? THREE.MOUSE.PAN
: null
controls.touches.ONE = enablePan ? THREE.TOUCH.PAN : null
controls.touches.TWO = THREE.TOUCH.DOLLY_ROTATE
}
@@ -1437,6 +1504,7 @@ const refreshPoiVisibilityByDistance = () => {
const handleControlChange = () => {
updatePoiVisibilityByDistance()
checkAutoSwitch()
scheduleModelAdjustIdleReport()
}
const clearProgrammaticCameraTimer = () => {
@@ -1567,6 +1635,10 @@ const updatePoiTapFeedback = (now: number) => {
const handleControlStart = () => {
activeControlGestureStartedAt = Date.now()
if (!isProgrammaticCameraChange) {
hasPendingManualModelAdjustment = true
clearModelAdjustReportTimer()
}
cancelCameraTween({ manual: true })
}
@@ -1577,6 +1649,7 @@ const handleControlEnd = () => {
}
activeControlGestureStartedAt = 0
updateLastControlDistance()
scheduleModelAdjustIdleReport()
}
const setProgress = (progress: number, message: string) => {
@@ -3375,6 +3448,21 @@ const fitCameraToObject = (object: THREE.Object3D, preset: CameraPreset = 'obliq
setCameraView(center, maxDim, direction, overviewFitOptions)
}
const applyOverviewInitialCamera = () => {
if (!camera || !controls) return
camera.position.copy(OVERVIEW_INITIAL_CAMERA_PARAMS.position)
camera.zoom = OVERVIEW_INITIAL_CAMERA_PARAMS.zoom
camera.updateProjectionMatrix()
controls.target.copy(OVERVIEW_INITIAL_CAMERA_PARAMS.target)
controls.update()
const distance = camera.position.distanceTo(controls.target)
if (Number.isFinite(distance)) {
lastControlDistance = distance
}
}
const resetCamera = () => {
if (activeModel) {
fitCameraToObject(activeModel)
@@ -3492,7 +3580,7 @@ const loadOverview = async () => {
applyModelVisibilityForView(activeModel, 'overview')
cacheAutoSwitchOverviewMaxDim(activeModel)
targetScene.add(activeModel)
fitCameraToObject(activeModel)
applyOverviewInitialCamera()
loadCurrentFloorPoiMarkersInBackground(loadToken)
resetAutoSwitchDistanceTracking()
refreshPoiVisibilityByDistance()
@@ -3523,7 +3611,7 @@ const loadOverview = async () => {
cachedOverviewModel = activeModel
cachedSharedModelUrl = packageData.overviewModelUrl
targetScene.add(activeModel)
fitCameraToObject(activeModel)
applyOverviewInitialCamera()
loadCurrentFloorPoiMarkersInBackground(loadToken)
resetAutoSwitchDistanceTracking()
refreshPoiVisibilityByDistance()
@@ -5090,6 +5178,8 @@ const disposeScene = () => {
clearOverviewWheelAutoSwitchTimer()
clearProgrammaticCameraTimer()
clearModelAdjustReportTimer()
hasPendingManualModelAdjustment = false
cameraTween = null
isProgrammaticCameraChange = false
lastControlDistance = 0