新增活跃工具层级管理,优化调色盘和放大镜工具的激活逻辑,确保用户交互流畅性和界面友好性。

This commit is contained in:
zihanjian
2025-06-06 15:15:56 +08:00
parent 711836f85a
commit 873284811b
4 changed files with 44 additions and 10 deletions

View File

@@ -172,6 +172,9 @@ export default function Home() {
endCol: number;
} | null>(null);
// 新增:活跃工具层级管理
const [activeFloatingTool, setActiveFloatingTool] = useState<'palette' | 'magnifier' | null>(null);
// 放大镜切换处理函数
const handleToggleMagnifier = () => {
const newActiveState = !isMagnifierActive;
@@ -183,6 +186,15 @@ export default function Home() {
}
};
// 激活工具处理函数
const handleActivatePalette = () => {
setActiveFloatingTool('palette');
};
const handleActivateMagnifier = () => {
setActiveFloatingTool('magnifier');
};
// 放大镜像素编辑处理函数
const handleMagnifierPixelEdit = (row: number, col: number, colorData: { key: string; color: string }) => {
if (!mappedPixelData) return;
@@ -2171,6 +2183,8 @@ export default function Home() {
onHighlightColor={handleHighlightColor}
isOpen={isFloatingPaletteOpen}
onToggleOpen={() => setIsFloatingPaletteOpen(!isFloatingPaletteOpen)}
isActive={activeFloatingTool === 'palette'}
onActivate={handleActivatePalette}
/>
)}
@@ -2188,6 +2202,8 @@ export default function Home() {
cellSize={gridDimensions ? Math.min(6, Math.max(4, 500 / Math.max(gridDimensions.N, gridDimensions.M))) : 6}
selectionArea={magnifierSelectionArea}
onClearSelection={() => setMagnifierSelectionArea(null)}
isFloatingActive={activeFloatingTool === 'magnifier'}
onActivateFloating={handleActivateMagnifier}
/>
{/* 放大镜选择覆盖层 */}

View File

@@ -22,6 +22,8 @@ interface FloatingColorPaletteProps {
onHighlightColor: (colorHex: string) => void;
isOpen: boolean;
onToggleOpen: () => void;
isActive: boolean;
onActivate: () => void;
}
const FloatingColorPalette: React.FC<FloatingColorPaletteProps> = ({
@@ -39,7 +41,9 @@ const FloatingColorPalette: React.FC<FloatingColorPaletteProps> = ({
onColorReplace,
onHighlightColor,
isOpen,
onToggleOpen
onToggleOpen,
isActive,
onActivate
}) => {
const [position, setPosition] = useState({ x: 20, y: 100 });
const [isDragging, setIsDragging] = useState(false);
@@ -50,6 +54,7 @@ const FloatingColorPalette: React.FC<FloatingColorPaletteProps> = ({
const handleMouseDown = useCallback((e: React.MouseEvent) => {
if (!paletteRef.current) return;
onActivate(); // 激活调色板,置于最上层
const rect = paletteRef.current.getBoundingClientRect();
setIsDragging(true);
setDragOffset({
@@ -57,12 +62,13 @@ const FloatingColorPalette: React.FC<FloatingColorPaletteProps> = ({
y: e.clientY - rect.top
});
e.preventDefault();
}, []);
}, [onActivate]);
// 处理触摸开始
const handleTouchStart = useCallback((e: React.TouchEvent) => {
if (!paletteRef.current) return;
onActivate(); // 激活调色板,置于最上层
const rect = paletteRef.current.getBoundingClientRect();
const touch = e.touches[0];
setIsDragging(true);
@@ -71,7 +77,7 @@ const FloatingColorPalette: React.FC<FloatingColorPaletteProps> = ({
y: touch.clientY - rect.top
});
e.preventDefault();
}, []);
}, [onActivate]);
// 处理移动
useEffect(() => {
@@ -160,13 +166,16 @@ const FloatingColorPalette: React.FC<FloatingColorPaletteProps> = ({
return (
<div
ref={paletteRef}
className="fixed bg-white dark:bg-gray-800 rounded-xl shadow-2xl border border-gray-200 dark:border-gray-600 z-50 select-none"
className={`fixed bg-white dark:bg-gray-800 rounded-xl shadow-2xl border border-gray-200 dark:border-gray-600 select-none ${
isActive ? 'z-[60]' : 'z-[50]'
}`}
style={{
left: position.x,
top: position.y,
width: '280px',
maxHeight: '400px'
}}
onClick={onActivate}
>
{/* 标题栏和控制按钮 */}
<div

View File

@@ -22,7 +22,7 @@ const FloatingToolbar: React.FC<FloatingToolbarProps> = ({
if (!isManualColoringMode) return null;
return (
<div className="fixed top-4 right-4 z-40 flex flex-col gap-2">
<div className="fixed top-4 right-4 z-[100] flex flex-col gap-2">
{/* 调色盘开关按钮 */}
<button
onClick={onTogglePalette}

View File

@@ -13,6 +13,8 @@ interface MagnifierToolProps {
cellSize: number;
selectionArea: SelectionArea | null;
onClearSelection: () => void;
isFloatingActive: boolean;
onActivateFloating: () => void;
}
interface SelectionArea {
@@ -30,7 +32,9 @@ const MagnifierTool: React.FC<MagnifierToolProps> = ({
selectedColorSystem,
onPixelEdit,
selectionArea,
onClearSelection
onClearSelection,
isFloatingActive,
onActivateFloating
}) => {
// 计算初始位置,确保在屏幕中央
const getInitialPosition = () => ({
@@ -160,11 +164,12 @@ const MagnifierTool: React.FC<MagnifierToolProps> = ({
});
}
onActivateFloating(); // 激活放大镜,置于最上层
setIsDragging(true);
// 阻止页面滚动
document.body.style.overflow = 'hidden';
event.preventDefault();
}, []);
}, [onActivateFloating]);
// 处理拖拽移动 - 触摸事件
const handleTitleBarTouchStart = useCallback((event: React.TouchEvent) => {
@@ -186,11 +191,12 @@ const MagnifierTool: React.FC<MagnifierToolProps> = ({
});
}
onActivateFloating(); // 激活放大镜,置于最上层
setIsDragging(true);
// 阻止页面滚动
document.body.style.overflow = 'hidden';
event.preventDefault();
}, []);
}, [onActivateFloating]);
const handleMouseMove = useCallback((event: MouseEvent) => {
if (isDragging) {
@@ -258,7 +264,7 @@ const MagnifierTool: React.FC<MagnifierToolProps> = ({
<>
{/* 选择区域提示 */}
{!selectionArea && (
<div className="fixed top-4 left-1/2 transform -translate-x-1/2 bg-blue-500 text-white px-4 py-2 rounded-lg shadow-lg z-50">
<div className="fixed top-4 left-1/2 transform -translate-x-1/2 bg-blue-500 text-white px-4 py-2 rounded-lg shadow-lg z-[70]">
<div className="flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
@@ -272,11 +278,14 @@ const MagnifierTool: React.FC<MagnifierToolProps> = ({
{selectionArea && (
<div
ref={magnifierRef}
className="fixed bg-white dark:bg-gray-800 rounded-xl shadow-2xl border border-gray-200 dark:border-gray-600 z-50 select-none"
className={`fixed bg-white dark:bg-gray-800 rounded-xl shadow-2xl border border-gray-200 dark:border-gray-600 select-none ${
isFloatingActive ? 'z-[60]' : 'z-[50]'
}`}
style={{
left: magnifierPosition.x,
top: magnifierPosition.y
}}
onClick={onActivateFloating}
>
{/* 标题栏 */}
<div