feat(minimap): add touch support for mobile interactions
- Implemented touch event handlers to enhance user experience on mobile devices. - Added functionality to show and update preview on touch start and move, regardless of dragging state. - Introduced a delay for hiding the preview after touch end to improve visibility of final position.
This commit is contained in:
1 parent
bbcd896584
commit
d7a30ea0cd
1 file changed
+79
-1
@@ -670,6 +670,79 @@ export const Minimap: React.FC<MinimapProps> = ({
|
||||
render();
|
||||
}, [state.dragging, renderPreview, render]);
|
||||
|
||||
// 追踪是否正在触控(用于区分移动端和桌面端交互)
|
||||
const isTouchingRef = useRef(false);
|
||||
|
||||
/**
|
||||
* 处理触控开始 - 显示预览(移动端 hover 效果)
|
||||
*/
|
||||
const handleTouchStart = useCallback((e: React.TouchEvent<HTMLCanvasElement>) => {
|
||||
isTouchingRef.current = true;
|
||||
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
|
||||
const touch = e.touches[0];
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const minimapX = touch.clientX - rect.left;
|
||||
const minimapY = touch.clientY - rect.top;
|
||||
|
||||
const pos = { x: minimapX, y: minimapY };
|
||||
setHoverPosition(pos);
|
||||
hoverPositionRef.current = pos;
|
||||
setPreviewVisible(true);
|
||||
|
||||
// 渲染预览
|
||||
renderPreview(minimapX, minimapY);
|
||||
|
||||
// 触发 minimap 重绘以显示预览区域指示框
|
||||
render();
|
||||
}, [renderPreview, render]);
|
||||
|
||||
/**
|
||||
* 处理触控移动 - 更新预览位置(移动端 hover 效果)
|
||||
* 移动端触控时始终显示预览,不受拖拽状态影响
|
||||
*/
|
||||
const handleTouchMove = useCallback((e: React.TouchEvent<HTMLCanvasElement>) => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
|
||||
const touch = e.touches[0];
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const minimapX = touch.clientX - rect.left;
|
||||
const minimapY = touch.clientY - rect.top;
|
||||
|
||||
const pos = { x: minimapX, y: minimapY };
|
||||
setHoverPosition(pos);
|
||||
hoverPositionRef.current = pos;
|
||||
|
||||
// 移动端触控时始终显示预览(不管是否在拖拽)
|
||||
setPreviewVisible(true);
|
||||
// 渲染预览
|
||||
renderPreview(minimapX, minimapY);
|
||||
|
||||
// 触发 minimap 重绘以显示预览区域指示框
|
||||
render();
|
||||
}, [renderPreview, render]);
|
||||
|
||||
/**
|
||||
* 处理触控结束 - 隐藏预览
|
||||
*/
|
||||
const handleTouchEnd = useCallback(() => {
|
||||
isTouchingRef.current = false;
|
||||
|
||||
// 延迟隐藏预览,给用户一点时间看到最终位置
|
||||
setTimeout(() => {
|
||||
// 只有在不再触控时才隐藏
|
||||
if (!isTouchingRef.current) {
|
||||
setPreviewVisible(false);
|
||||
setHoverPosition(null);
|
||||
hoverPositionRef.current = null;
|
||||
render();
|
||||
}
|
||||
}, 500); // 延长到 500ms,让用户更清楚看到最终位置
|
||||
}, [render]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!state.expanded) return;
|
||||
|
||||
@@ -705,13 +778,15 @@ export const Minimap: React.FC<MinimapProps> = ({
|
||||
};
|
||||
|
||||
// 计算预览框位置(在 minimap 左侧)
|
||||
// 移动端触控时(isTouchingRef.current)即使拖拽也显示预览
|
||||
const shouldShowPreview = previewVisible && (isTouchingRef.current || !state.dragging);
|
||||
const previewStyle: React.CSSProperties = hoverPosition ? {
|
||||
position: 'absolute',
|
||||
right: config.width + 8, // 在 minimap 左侧
|
||||
top: Math.max(0, Math.min(hoverPosition.y - PREVIEW_SIZE / 2, config.height - PREVIEW_SIZE)),
|
||||
width: PREVIEW_SIZE,
|
||||
height: PREVIEW_SIZE,
|
||||
opacity: previewVisible && !state.dragging ? 1 : 0,
|
||||
opacity: shouldShowPreview ? 1 : 0,
|
||||
pointerEvents: 'none',
|
||||
transition: 'opacity 0.15s ease-out, top 0.1s ease-out',
|
||||
} : {
|
||||
@@ -741,6 +816,9 @@ export const Minimap: React.FC<MinimapProps> = ({
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
onMouseMove={handleMouseMove}
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchMove={handleTouchMove}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
style={{
|
||||
cursor: state.dragging ? 'grabbing' : 'pointer',
|
||||
}}
|
||||
|
||||
Reference in new issue
Block a user