- 标记点角标从物品数量改为按楼层顺序编号,角标背景色跟随标记颜色 - FoldableLayout 改为绝对定位叠加布局,移除 LayoutAnimation(解决 Android 地图渲染空白及卡顿) - PhotoPicker 拆分为拍照/选图两个独立按钮;选图改用 expo-document-picker 绕过三星 Photo Picker 崩溃问题 - AndroidManifest 移除手动 FileProvider 声明(改由 Expo 插件自动注入) - 同步更新蓝图文档:新增 category-management 模块、补全各模块已完成任务卡 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.8 KiB
3.8 KiB
| id | name | area | status |
|---|---|---|---|
| floor-map | 楼层地图与标记点管理 | rn-app | 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(原生 Image,from imageUri)② SVG 矢量路径(SvgXml,overdraw 预渲染提升缩放清晰度,动态计算安全 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 API;Pinch 手势控制缩放(MIN_SCALE=1, MAX_SCALE=5);Pan 手势(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 文件;提取背景 JPEG(imageUri)+ 用户嵌入图片(embeddedImages,含 cx/cy/width/height/angleDeg/opacity);从 svgXml 中去除所有 image 元素及 Inkscape 私有命名空间;生成 floorMaps.generated.ts TypeScript 文件
决策记录
- SVG 三层渲染架构:
SvgXml无法可靠渲染带rotate/matrixtransform 的<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 语义一致,无需额外偏移修正。