import { useState, useRef } from 'react'; import Draggable, { type DraggableEvent, type DraggableData } from 'react-draggable'; import { Gamepad2 } from 'lucide-react'; interface FloatingButtonProps { onClick: () => void; } export function FloatingButton({ onClick }: FloatingButtonProps) { const [position, setPosition] = useState({ x: 20, y: 100 }); const [isDragging, setIsDragging] = useState(false); const [isIdle, setIsIdle] = useState(false); const nodeRef = useRef(null); const idleTimerRef = useRef(null); const dragRef = useRef(false); // Track real drag movement // 清除空闲倒计时 const clearIdleTimer = () => { if (idleTimerRef.current) { clearTimeout(idleTimerRef.current); idleTimerRef.current = null; } setIsIdle(false); }; const handleDragStart = () => { dragRef.current = false; clearIdleTimer(); setIsDragging(true); // 如果处于空闲状态(半隐藏),视觉上立刻恢复原状 if (isIdle) { setPosition(prev => { const btnWidth = nodeRef.current ? nodeRef.current.offsetWidth : 48; return { ...prev, x: prev.x < 0 ? 0 : window.innerWidth - btnWidth }; }); } }; const handleDrag = (_e: DraggableEvent, data: DraggableData) => { dragRef.current = true; setPosition({ x: data.x, y: data.y }); }; const handleDragStop = (_e: DraggableEvent, data: DraggableData) => { setIsDragging(false); if (!dragRef.current) { onClick(); } // 自动吸附屏幕左右边缘 const btnWidth = nodeRef.current ? nodeRef.current.offsetWidth : 48; // 默认 48px const btnHeight = nodeRef.current ? nodeRef.current.offsetHeight : 48; // 限制不要拖出上下边缘 let endY = data.y; const maxY = window.innerHeight - btnHeight; endY = Math.max(0, Math.min(endY, maxY)); let endX = data.x; const centerX = data.x + (btnWidth / 2); const windowCenterX = window.innerWidth / 2; endX = centerX < windowCenterX ? 0 : window.innerWidth - btnWidth; setPosition({ x: endX, y: endY }); // 启动 3 秒空闲隐藏计时器 idleTimerRef.current = setTimeout(() => { setIsIdle(true); // 将半个按钮宽度移出屏幕之外 setPosition(prev => { const halfWidth = btnWidth / 2; const newX = prev.x < windowCenterX ? -halfWidth : window.innerWidth - halfWidth; return { ...prev, x: newX }; }); }, 3000); }; return (
); }