fix(minimap): hit-test against clamped rect + shrink to 100x75
Two unrelated minimap issues from user feedback: 1. Click on the red viewport rect was sometimes teleporting the canvas instead of starting a drag. Cause: insideRect compared click coords against the UNCLAMPED rectX/rectY/rectW/rectH, but the rendered rect uses clampedX/clampedY (which differ when the user pans past a world edge). The user clicked on the visible red rect, but the logical rect was off-minimap → insideRect returned false → fell through to the teleport branch. Fix: compute clamped values once at the top, render and hit-test against the same values. Drag now only fires when the click really lands inside the visible rect. 2. The 140x105 default still ate too much canvas at typical zoom. Drop to 100x75 (12% of world width by 2.5%, same proportions as the world). Mobile breakpoint dropped to 90x68 to stay proportionally smaller on phones.
This commit is contained in:
parent
218a891c6d
commit
6242b7f16b
|
|
@ -70,8 +70,8 @@
|
|||
@media (max-width: 720px) {
|
||||
/* On phones the minimap eats too much of the canvas; shrink it. */
|
||||
.canvas-minimap {
|
||||
width: 140px !important;
|
||||
height: 105px !important;
|
||||
width: 90px !important;
|
||||
height: 68px !important;
|
||||
bottom: 12px;
|
||||
right: 12px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ import type { Component } from '../../types/components';
|
|||
import type { BoardInstance } from '../../types/board';
|
||||
import './CanvasMinimap.css';
|
||||
|
||||
const MINIMAP_W = 140;
|
||||
const MINIMAP_H = 105;
|
||||
const MINIMAP_W = 100;
|
||||
const MINIMAP_H = 75;
|
||||
const WORLD_W = 4000;
|
||||
const WORLD_H = 3000;
|
||||
const SCALE_X = MINIMAP_W / WORLD_W;
|
||||
|
|
@ -81,6 +81,17 @@ export const CanvasMinimap: React.FC<Props> = ({
|
|||
const rectW = (vp.w / zoom) * SCALE_X;
|
||||
const rectH = (vp.h / zoom) * SCALE_Y;
|
||||
|
||||
// Clamp the rectangle to the minimap bounds so it never paints outside
|
||||
// (transiently during pinch-zoom-out, and persistently when the user
|
||||
// pans past a world edge). We hit-test against these clamped values
|
||||
// too — otherwise clicking the visible red rect can fall outside the
|
||||
// unclamped logical rect and erroneously trigger a teleport instead
|
||||
// of a drag.
|
||||
const clampedW = Math.min(rectW, MINIMAP_W);
|
||||
const clampedH = Math.min(rectH, MINIMAP_H);
|
||||
const clampedX = Math.max(0, Math.min(MINIMAP_W - clampedW, rectX));
|
||||
const clampedY = Math.max(0, Math.min(MINIMAP_H - clampedH, rectY));
|
||||
|
||||
// Drag state. We use a ref + window listeners (rather than React's
|
||||
// onMouseMove on the minimap div) so the gesture keeps working even if
|
||||
// the cursor leaves the minimap during a fast pan.
|
||||
|
|
@ -137,10 +148,10 @@ export const CanvasMinimap: React.FC<Props> = ({
|
|||
const localX = e.clientX - rect.left;
|
||||
const localY = e.clientY - rect.top;
|
||||
const insideRect =
|
||||
localX >= rectX &&
|
||||
localX <= rectX + rectW &&
|
||||
localY >= rectY &&
|
||||
localY <= rectY + rectH;
|
||||
localX >= clampedX &&
|
||||
localX <= clampedX + clampedW &&
|
||||
localY >= clampedY &&
|
||||
localY <= clampedY + clampedH;
|
||||
if (insideRect) {
|
||||
// Drag mode — record start state, window listeners do the rest.
|
||||
dragRef.current = {
|
||||
|
|
@ -155,7 +166,7 @@ export const CanvasMinimap: React.FC<Props> = ({
|
|||
teleportTo(localX / SCALE_X, localY / SCALE_Y);
|
||||
}
|
||||
},
|
||||
[rectX, rectY, rectW, rectH, pan, teleportTo],
|
||||
[clampedX, clampedY, clampedW, clampedH, pan, teleportTo],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -186,13 +197,6 @@ export const CanvasMinimap: React.FC<Props> = ({
|
|||
};
|
||||
}, [zoom, setPan, clampPan]);
|
||||
|
||||
// Clamp the rendered rectangle to the minimap bounds so it never paints
|
||||
// outside (happens transiently during pinch-zoom-out).
|
||||
const clampedX = Math.max(0, Math.min(MINIMAP_W - rectW, rectX));
|
||||
const clampedY = Math.max(0, Math.min(MINIMAP_H - rectH, rectY));
|
||||
const clampedW = Math.min(rectW, MINIMAP_W);
|
||||
const clampedH = Math.min(rectH, MINIMAP_H);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={minimapRef}
|
||||
|
|
|
|||
Loading…
Reference in New Issue