react-phone-apps/.blueprint/modules/floor-map.md
lanrtop 3dbc6f0ff5 refactor: 标记点序号显示、布局叠加方式及照片选择器重构
- 标记点角标从物品数量改为按楼层顺序编号,角标背景色跟随标记颜色
- FoldableLayout 改为绝对定位叠加布局,移除 LayoutAnimation(解决 Android 地图渲染空白及卡顿)
- PhotoPicker 拆分为拍照/选图两个独立按钮;选图改用 expo-document-picker 绕过三星 Photo Picker 崩溃问题
- AndroidManifest 移除手动 FileProvider 声明(改由 Expo 插件自动注入)
- 同步更新蓝图文档:新增 category-management 模块、补全各模块已完成任务卡

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 02:17:34 +09:00

57 lines
3.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: floor-map
name: 楼层地图与标记点管理
area: rn-app
status: done
---
## 概述
以真实 SVG 楼层平面图为底图,支持捏合缩放、单指平移、长按添加标记点、拖拽移动标记点。支持 1F/2F/3F/楼顶四个楼层。SVG 内嵌图片通过构建脚本提取,分层以原生 Image 渲染,保证清晰度和旋转精度。
## 任务卡
### ✅ SVG 地图渲染(多层架构)
- status: done
- complexity: M
- files: apps/property-survey/src/features/map/FloorMap.tsx, apps/property-survey/src/features/map/floorMaps.generated.ts, apps/property-survey/scripts/generate-maps.js
- acceptance: 三层渲染:① 底图 JPEG原生 Imagefrom imageUri② SVG 矢量路径SvgXmloverdraw 预渲染提升缩放清晰度,动态计算安全 overdraw 倍数避免 Android Canvas OOM③ 用户嵌入图片(原生 Image从 SVG 提取并按 SVG matrix/rotate 变换还原坐标和旋转角)
### ✅ 捏合缩放 + 单指平移手势
- status: done
- complexity: M
- files: apps/property-survey/src/features/map/FloorMap.tsx
- acceptance: 使用 react-native-gesture-handler Gesture APIPinch 手势控制缩放MIN_SCALE=1, MAX_SCALE=5Pan 手势minPointers:1, maxPointers:1控制平移双指和单指通过 Gesture.Race 互斥;使用 react-native-reanimated SharedValue 实现原生线程动画
### ✅ 长按添加标记点
- status: done
- complexity: M
- files: apps/property-survey/src/features/map/FloorMap.tsx
- acceptance: LongPress 手势minDuration:500ms触点坐标反算缩放/平移变换得到地图相对坐标0~1调用 insertMarker 写入数据库;与双指手势通过 Gesture.Race 互斥
### ✅ 标记点图标组件
- status: done
- complexity: M
- files: apps/property-survey/src/features/map/MapMarker.tsx
- depends: floor-map
- acceptance: 按相对坐标绝对定位;已有物品的标记点显示彩色图钉 + 数量角标(颜色来自 marker.color选中状态有缩放高亮支持拖拽移动Pan 手势,拖拽结束调用 onDragEnd
### ✅ 楼层标记点数据加载与标记列表
- status: done
- complexity: S
- files: apps/property-survey/src/features/map/MarkerList.tsx
- depends: floor-map
- acceptance: 楼层切换或 refreshKey 变化时重新查询;左侧边栏展示当前楼层所有标记点卡片(标签、物品列表含确认状态图标);删除标记点时弹确认对话框含级联删除提示
### ✅ SVG 地图生成脚本
- status: done
- complexity: M
- files: scripts/generate-maps.js, apps/property-survey/img/1101-1104.svg
- acceptance: 读取 4 个 SVG 文件;提取背景 JPEGimageUri+ 用户嵌入图片embeddedImages含 cx/cy/width/height/angleDeg/opacity从 svgXml 中去除所有 image 元素及 Inkscape 私有命名空间;生成 floorMaps.generated.ts TypeScript 文件
## 决策记录
- **SVG 三层渲染架构**`SvgXml` 无法可靠渲染带 `rotate`/`matrix` transform 的 `<image>` 元素(坐标偏移、旋转不准)。改为构建时提取:① 背景 JPEG 用原生 `Image` 渲染(性能好);② 矢量路径用 `SvgXml` 渲染(保留矢量清晰度);③ 用户嵌入图片用原生 `Image` 渲染(精确还原旋转和位置)。
- **SVG overdraw 预渲染**`SvgXml` 在 RN 中被光栅化为固定分辨率纹理,缩放时模糊。通过以 N 倍宽高渲染再 `scale(1/N)` 缩回,在 Android Canvas 安全内存上限内最大化预渲染分辨率。N 值由 `calcSafeOverdraw()` 根据 `PixelRatio.get()` 动态计算,避免高 DPI 设备 OOM。
- **嵌入图片坐标还原**SVG `matrix(a,b,c,d,e,f)` 变换的图片中心点计算公式:`cx = a*(ox+W/2) + c*(oy+H/2) + e`,旋转角 `angleDeg = atan2(b,a) * 180/π`。RN 中 Image 的 `transform: rotate` 以元素自身中心为锚点,与 SVG transform 语义一致,无需额外偏移修正。