diff --git a/src/app/components/VirtualTour.tsx b/src/app/components/VirtualTour.tsx index 6a415c5..62842ed 100644 --- a/src/app/components/VirtualTour.tsx +++ b/src/app/components/VirtualTour.tsx @@ -2941,14 +2941,30 @@ function MiniMap({ const nodeSize = compact ? 5.2 : 5.2; const edgeInset = nodeSize / 2; const clampMapPoint = (value: number) => THREE.MathUtils.clamp(value, edgeInset, 100 - edgeInset); - const compressOverviewY = (value: number) => 50 + (value - 50) * 0.86; + + // Auto-fit overview: co toàn bộ điểm vào khung với lề an toàn để không bị cắt. + const OVERVIEW_MARGIN = 8; + const overviewPts = scenes + .map((s) => s.mapPosition) + .filter((p): p is { x: number; y: number } => Boolean(p)); + const overviewBounds = { + minX: Math.min(...overviewPts.map((p) => p.x)), + maxX: Math.max(...overviewPts.map((p) => p.x)), + minY: Math.min(...overviewPts.map((p) => p.y)), + maxY: Math.max(...overviewPts.map((p) => p.y)), + }; + const fitOverview = (value: number, min: number, max: number) => + max - min < 0.0001 + ? 50 + : OVERVIEW_MARGIN + ((value - min) / (max - min)) * (100 - 2 * OVERVIEW_MARGIN); + const getMapPosition = (scene: TourScene) => { if (!scene.mapPosition || (!isOverview && !activeScene.mapPosition)) return null; if (isOverview) { return { - x: clampMapPoint(scene.mapPosition.x), - y: clampMapPoint(compressOverviewY(scene.mapPosition.y)), + x: clampMapPoint(fitOverview(scene.mapPosition.x, overviewBounds.minX, overviewBounds.maxX)), + y: clampMapPoint(fitOverview(scene.mapPosition.y, overviewBounds.minY, overviewBounds.maxY)), }; }