# 图片编辑器移动端适配 ## 摘要 为图片编辑器(ImageEditor)添加移动端触摸事件支持,使画笔和文本工具能在移动设备上使用。 ## 当前状态分析 ### 核心问题 Canvas 元素只绑定了鼠标事件,未绑定触摸事件: ```tsx // 当前实现 - 仅支持鼠标 ``` ### 受影响功能 - **画笔工具**: 无法在触摸屏上绘画 - **文本工具**: 无法在触摸屏上点击放置文本 ## 实施步骤 ### 步骤 1:添加触摸坐标获取函数 在 ImageEditor.tsx 中添加通用的位置获取函数: ```tsx // 获取鼠标或触摸位置 const getEventPosition = (e: React.MouseEvent | React.TouchEvent) => { const canvas = canvasRef.current; if (!canvas) return null; const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const scaleY = canvas.height / rect.height; let clientX: number, clientY: number; if ('touches' in e) { const touch = e.touches[0] || e.changedTouches[0]; if (!touch) return null; clientX = touch.clientX; clientY = touch.clientY; } else { clientX = e.clientX; clientY = e.clientY; } return { x: (clientX - rect.left) * scaleX, y: (clientY - rect.top) * scaleY, }; }; ``` ### 步骤 2:添加触摸事件处理函数 ```tsx // 触摸开始 const handleTouchStart = (e: React.TouchEvent) => { e.preventDefault(); const pos = getEventPosition(e); if (!pos) return; if (activeTool === "brush") { setIsDrawing(true); const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; ctx.beginPath(); ctx.moveTo(pos.x, pos.y); ctx.strokeStyle = brushColor; ctx.lineWidth = brushSize; ctx.lineCap = "round"; ctx.lineJoin = "round"; } }; // 触摸移动 const handleTouchMove = (e: React.TouchEvent) => { e.preventDefault(); if (!isDrawing || activeTool !== "brush") return; const pos = getEventPosition(e); if (!pos) return; const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; ctx.lineTo(pos.x, pos.y); ctx.stroke(); }; // 触摸结束 const handleTouchEnd = (e: React.TouchEvent) => { e.preventDefault(); if (isDrawing) { setIsDrawing(false); saveHistory(); } }; ``` ### 步骤 3:修改文本工具点击处理 ```tsx const handleCanvasTouchTap = (e: React.TouchEvent) => { e.preventDefault(); if (activeTool !== "text" || !textInput.trim()) return; const pos = getEventPosition(e); if (!pos) return; const newText: TextItem = { id: Math.random().toString(36).substring(2, 9), text: textInput, x: pos.x, y: pos.y, fontSize: textSize, color: textColor, }; setTexts((prev) => [...prev, newText]); saveHistory(); }; ``` ### 步骤 4:更新 Canvas JSX ```tsx ``` ### 步骤 5:添加 CSS 触摸优化 在 ImageEditor.css 中添加: ```css /* 防止浏览器默认触摸行为 */ .ie-canvas { touch-action: none; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; } /* 移动端画布区域优化 */ @media (max-width: 768px) { .ie-canvas { max-width: 100%; height: auto; } .ie-tool-btn { min-width: 48px; min-height: 48px; } } ``` ## 涉及的文件 | 文件 | 操作 | |------|------| | `src/pages/ImageEditor/ImageEditor.tsx` | 添加触摸事件处理函数和位置获取函数 | | `src/pages/ImageEditor/ImageEditor.css` | 添加触摸优化样式 | ## 验证步骤 1. 运行 TypeScript 编译检查:`npx tsc --noEmit` 2. 启动开发服务器:`npm run dev` 3. 在移动设备或浏览器开发者工具中测试: - 画笔工具:手指在画布上滑动应该能绘制线条 - 文本工具:手指点击画布应该能放置文本 - 其他功能(亮度、滤镜等)应该正常工作 ## 注意事项 - 触摸事件需要 `e.preventDefault()` 阻止默认行为(如页面滚动) - `touch-action: none` 防止浏览器处理触摸手势 - 坐标转换需要考虑 Canvas 的缩放比例 - 触摸事件使用 `e.touches[0]` 获取第一个触摸点