diff --git a/web/src/components/game/Viewport.vue b/web/src/components/game/Viewport.vue index aae58c6..baf193a 100644 --- a/web/src/components/game/Viewport.vue +++ b/web/src/components/game/Viewport.vue @@ -50,25 +50,32 @@ function fitMap() { // Don't fit if world is default small if (worldWidth < 100) return - viewport.resize(props.screenWidth, props.screenHeight, worldWidth, worldHeight) - viewport.fit(true, worldWidth, worldHeight) - + // 1. 先计算新的缩放限制 const fitScale = Math.min(props.screenWidth / worldWidth, props.screenHeight / worldHeight) - // Allow zooming out a bit more than fit - viewport.clampZoom({ minScale: fitScale * 0.8, maxScale: 4.0 }) - // If current zoom is weird, reset - if (viewport.scaled < fitScale) viewport.setZoom(fitScale) + // 2. 重要:在 fit() 之前先设置新的 clampZoom,或者先暂时移除旧的限制 + // 这里我们直接设置新的宽松限制 + viewport.clampZoom({ minScale: fitScale * 0.8, maxScale: 4.0 }) + + // 3. 更新尺寸 + viewport.resize(props.screenWidth, props.screenHeight, worldWidth, worldHeight) + + // 4. 执行适配,并在中心位置 + viewport.fit(true, worldWidth, worldHeight) + viewport.moveCenter(worldWidth / 2, worldHeight / 2) + + // 5. 如果当前缩放比预期的还要大(虽然 fit 应该已经处理了,但双保险),强制设置 + if (viewport.scaled > fitScale * 1.1) { // 允许一点误差 + viewport.setZoom(fitScale) + } } watch(() => [props.screenWidth, props.screenHeight], ([w, h]) => { if (viewport) { - viewport.resize(w, h, props.worldWidth, props.worldHeight) - // Optional: Refit on significant resize or just clamp? - // clampZoom updates automatically if minScale is not dynamic? - // No, we set minScale manually. We should re-clamp. + // 窗口大小改变时,重新计算最小缩放值,防止用户看到黑边 const fitScale = Math.min(w / props.worldWidth, h / props.worldHeight) viewport.clampZoom({ minScale: fitScale * 0.8, maxScale: 4.0 }) + viewport.resize(w, h, props.worldWidth, props.worldHeight) } })