style: 调整pad端横屏竖屏的问题

This commit is contained in:
zhanghao 2026-08-05 16:54:26 +08:00
parent 520811e883
commit 4602ec9e74
3 changed files with 94 additions and 17 deletions

View File

@ -18,6 +18,7 @@ const autoFitOptions = {
}
let viewportWidth = document.documentElement.clientWidth
let autoFitResetTimer: ReturnType<typeof setTimeout> | undefined
const initAutoFit = () => {
autofit.init(autoFitOptions, false)
@ -29,29 +30,36 @@ const resetAutoFit = () => {
viewportWidth = document.documentElement.clientWidth
}
const scheduleAutoFitReset = () => {
clearTimeout(autoFitResetTimer)
// resize autofit
autoFitResetTimer = setTimeout(resetAutoFit, 50)
}
const handleResize = () => {
const nextWidth = document.documentElement.clientWidth
//
if (Math.abs(nextWidth - viewportWidth) <= 2) return
resetAutoFit()
scheduleAutoFitReset()
}
onMounted(() => {
initAutoFit()
window.addEventListener('resize', handleResize)
window.addEventListener('orientationchange', resetAutoFit)
document.addEventListener('fullscreenchange', resetAutoFit)
document.addEventListener('webkitfullscreenchange', resetAutoFit)
window.addEventListener('orientationchange', scheduleAutoFitReset)
document.addEventListener('fullscreenchange', scheduleAutoFitReset)
document.addEventListener('webkitfullscreenchange', scheduleAutoFitReset)
})
onUnmounted(() => {
autofit.off('#app')
clearTimeout(autoFitResetTimer)
window.removeEventListener('resize', handleResize)
window.removeEventListener('orientationchange', resetAutoFit)
document.removeEventListener('fullscreenchange', resetAutoFit)
document.removeEventListener('webkitfullscreenchange', resetAutoFit)
window.removeEventListener('orientationchange', scheduleAutoFitReset)
document.removeEventListener('fullscreenchange', scheduleAutoFitReset)
document.removeEventListener('webkitfullscreenchange', scheduleAutoFitReset)
})
</script>

View File

@ -25,6 +25,8 @@ import { onBeforeUnmount, onMounted, ref } from 'vue'
const isPortraitTablet = ref(false)
let portraitMediaQuery
let orientationFrame
const orientationTimers = new Set()
const isTablet = () => {
const userAgent = navigator.userAgent
@ -40,11 +42,32 @@ const isTablet = () => {
}
const updateOrientation = () => {
const isPortrait = portraitMediaQuery?.matches ?? window.innerHeight > window.innerWidth
const viewport = window.visualViewport
const viewportWidth = viewport?.width || window.innerWidth
const viewportHeight = viewport?.height || window.innerHeight
const isPortrait = viewportHeight > viewportWidth
isPortraitTablet.value = isTablet() && isPortrait
document.documentElement.classList.toggle('is-portrait-tablet', isPortraitTablet.value)
}
const scheduleOrientationUpdate = () => {
updateOrientation()
cancelAnimationFrame(orientationFrame)
orientationFrame = requestAnimationFrame(updateOrientation)
orientationTimers.forEach(clearTimeout)
orientationTimers.clear()
// iPad
for (const delay of [80, 180, 350]) {
const timer = setTimeout(() => {
orientationTimers.delete(timer)
updateOrientation()
}, delay)
orientationTimers.add(timer)
}
}
const tryLockLandscape = async () => {
if (!isTablet() || !screen.orientation?.lock) return
@ -60,17 +83,22 @@ onMounted(() => {
updateOrientation()
tryLockLandscape()
portraitMediaQuery.addEventListener?.('change', updateOrientation)
window.addEventListener('resize', updateOrientation)
window.addEventListener('orientationchange', updateOrientation)
portraitMediaQuery.addEventListener?.('change', scheduleOrientationUpdate)
window.addEventListener('resize', scheduleOrientationUpdate)
window.addEventListener('orientationchange', scheduleOrientationUpdate)
window.visualViewport?.addEventListener('resize', scheduleOrientationUpdate)
document.addEventListener('fullscreenchange', tryLockLandscape)
})
onBeforeUnmount(() => {
document.documentElement.classList.remove('is-portrait-tablet')
portraitMediaQuery?.removeEventListener?.('change', updateOrientation)
window.removeEventListener('resize', updateOrientation)
window.removeEventListener('orientationchange', updateOrientation)
cancelAnimationFrame(orientationFrame)
orientationTimers.forEach(clearTimeout)
orientationTimers.clear()
portraitMediaQuery?.removeEventListener?.('change', scheduleOrientationUpdate)
window.removeEventListener('resize', scheduleOrientationUpdate)
window.removeEventListener('orientationchange', scheduleOrientationUpdate)
window.visualViewport?.removeEventListener('resize', scheduleOrientationUpdate)
document.removeEventListener('fullscreenchange', tryLockLandscape)
})
</script>

View File

@ -94,6 +94,9 @@ const containerRef = ref(null)
const mapCanvasRef = ref(null)
let resizeObserver
let eventsBound = false
let orientationObserver
let animationFrameId = null
let isRendering = false
const init = () => {
mapCanvas = mapCanvasRef.value;
@ -214,6 +217,8 @@ async function loadMapIntoApplication(parsedMap) {
* @param {number} timestamp - requestAnimationFrame 提供的时间戳毫秒
*/
function renderFrame(timestamp) {
if (!isRendering || !canvasCtx) return;
//
applicationState.animationTimeSeconds = (timestamp || 0) / 1000;
@ -223,7 +228,7 @@ function renderFrame(timestamp) {
//
if (!applicationState.isMapLoaded) {
requestAnimationFrame(renderFrame); //
animationFrameId = requestAnimationFrame(renderFrame); //
return;
}
@ -273,7 +278,36 @@ function renderFrame(timestamp) {
drawMapBoundary(canvasCtx, map, applicationState);
//
requestAnimationFrame(renderFrame);
animationFrameId = requestAnimationFrame(renderFrame);
}
const stopRendering = () => {
isRendering = false
if (animationFrameId !== null) {
cancelAnimationFrame(animationFrameId)
animationFrameId = null
}
}
const startRendering = () => {
if (isRendering || !applicationState.isMapLoaded || document.documentElement.classList.contains('is-portrait-tablet')) return
isRendering = true
animationFrameId = requestAnimationFrame(renderFrame)
}
const handleOrientationVisibility = () => {
if (document.documentElement.classList.contains('is-portrait-tablet')) {
stopRendering()
return
}
// v-show Vue
nextTick(() => {
requestAnimationFrame(() => {
resizeCanvasToContainer()
startRendering()
})
})
}
const drawAllRobots = (ctx) => {
@ -495,6 +529,11 @@ onMounted(() => {
resizeObserver = new ResizeObserver(resizeCanvasToContainer)
resizeObserver.observe(containerRef.value)
window.addEventListener('resize', resizeCanvasToContainer)
orientationObserver = new MutationObserver(handleOrientationVisibility)
orientationObserver.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
})
})
watch(() => props.mapName,
@ -502,7 +541,7 @@ watch(() => props.mapName,
if (newVal) {
await loadSourceMap(newVal)
addRobot(robotStore.ip, robotStore.ip, robotStore.position.x, robotStore.position.y, robotStore.position.theta, getThemeColor('--color-canvas-robot'))
requestAnimationFrame(renderFrame);
startRendering()
}
}, {
immediate: true
@ -515,8 +554,10 @@ defineExpose({
})
onUnmounted(() => {
stopRendering()
window.removeEventListener('resize', resizeCanvasToContainer)
resizeObserver?.disconnect()
orientationObserver?.disconnect()
canvasCtx = null
})
</script>