
拆解 floorplan-3d 单文件架构2600 行 HTML 里的完整 2D/3D 户型设计工具是怎么组织的【免费下载链接】floorplan-3d项目地址: https://gitcode.com/gh_mirrors/fl/floorplan-3dfloorplan-3d 是一个纯前端的 2D/3D 户型设计工具在 SVG 平面图上拖家具、拆墙体、量尺寸一键切换到 Three.js 3D 场景支持鸟瞰与第一人称漫游。整个应用只有 index.html 一个文件约 2674 行无框架、无构建浏览器打开即用。本文按源码结构逐层拆解这个「单文件完整工具」是如何组织的。快速上手零构建运行这个户型设计工具git clone https://gitcode.com/gh_mirrors/fl/floorplan-3d cd floorplan-3d # 直接用浏览器打开 index.html或 python3 -m http.server 8000 # 访问 http://localhost:8000Three.js 通过 CDN 加载首次进入 3D 场景需要联网见 README.md 的快速开始一节。文件地图4 大块各管一段单文件 ≠ 一团乱麻。index.html 从上到下分为 4 个职责清晰的大块这也是本文拆解的路线图位置内容规模L11–L216全部 CSS布局、2D/3D 切换动画、触屏与窄屏适配~200 行L217–L222importmap声明 three.js CDN 模块5 行L224–L343页面骨架顶栏工具条、家具库、SVG 画布、属性面板~120 行L345–L1508经典脚本2D 数据 交互 SVG 渲染~1160 行L1509–L2672ES Module 脚本Three.js 3D 场景~1160 行# 用这个命令就能看清全部分区注释行是分界标志 grep -n index.html2D 部分数据先行渲染全是「字符串模板」户型数据就是几组常量数组2D 部分最核心的设计是先定义数据再谈一切。所有户型信息以毫米为单位的纯数组/对象写死在脚本开头WALLS墙体线段 类型承重/外墙/可拆/矮墙见 L395–L421WINS/DOORS/SLIDES窗洞、平开门含铰点与开启方向、推拉门见 L423–L443ROOMS房间多边形 默认地面材料见 L445–L459MATS8 种地面材料及单价用于造价估算见 L460–L469LIB6 大类 60 余种家具家电类型、名称、真实尺寸、颜色见 L471–L499默认布置方案由defaultFurniture()生成L506–L537配合defaultState()构成初始状态。一个 state 对象 快照式撤销运行时状态只有一个state家具、房间材料、已拆墙体、测量线见 L565–L579。它的组织方式极其朴素任何修改都走mutate(fn)先快照JSON.stringify(state)压入撤销栈上限 150 步执行修改后统一renderAll()localStorage以huxing-design-v1为键自动保存刷新不丢方案撤销/重做 弹出快照反序列化没有复杂的操作逆运算这套「全量快照」策略让撤销逻辑 10 行内搞定代价只是内存里存了几十份 JSON对单页工具完全可接受。SVG 图层分组 innerHTML 整体重绘页面骨架里2D 画布是一个 SVG内部按渲染顺序分了 9 个g图层网格、房间、家具、墙体、门窗、房间名、尺寸标注、测量线、选中框见 L306–L317。渲染函数renderRooms/renderFurn/renderWalls…L726–L867的策略是拼字符串再整体塞进innerHTML而不是操作 DOM 节点每种家具的 2D 图例由furnSVG(type, w, d, color)一个 switch 生成L625–L724床有枕头被子、沙发有扶手分块全按真实毫米尺寸绘制地面材料是 SVGpattern图案木地板拼缝、大理石纹理由buildDefs()生成见 L594–L615尺寸标注链、测量线、选中手柄旋转点/缩放方块也都是字符串模板交互层则是一组 Pointer 事件拖移带 10mm 网格 贴墙吸附L1142–L1164、双指捏合缩放、触屏手柄加大COARSE/TAP常量L556–L558、家具库「幽灵图」拖放L1321–L1385。键盘快捷键集中在一个 keydown 监听里L1293–L1319。右侧属性面板总览/房间/家具三种形态同样是「HTML 字符串 绑定事件」的套路见 L876–L1056。3D 部分独立 ES Modulethree.js 全在这半边3D 场景放在单独的script typemodule里L1509 起通过 importmap 从 CDN 引入 three.js r160 及 OrbitControls、PointerLockControls 等附加件L1516–L1521。组织上仍是「数据 → 构建 → 渲染」的清晰链条初始化L1536–L1628WebGLRenderer 阴影 ACES 色调映射半球光 可移动的「太阳」平行光RoomEnvironment 生成环境反射贴图。场景按 Group 分层地板层、墙体层、家具层、标签层、灯具层。程序化地面贴图L1653–L1687用 Canvas 现画木纹拼缝、大理石纹、水磨石颗粒再包成CanvasTexture按真实米数平铺——连贴图都不需要外部文件。几何小工具库L1689–L1784box/rbox/cyl/lathe/rod/tube/blob等十几个函数统一「y 底面高度」的约定还有柜门分缝 拉手的fronts()、收分腿的legs()。这是 3D 家具模型的积木。buildFurniture(f)L1787–L2272约 490 行与 2D 的furnSVG一一对应的 switch把 60 余种家具逐一建模——软包床头、金属陶瓷材质、带环境反射的冰箱门、52 个键的钢琴……每件的随机装饰书架上的书、绿植叶片由种子随机函数rng()保证同一件家具每次长一样。建筑构建buildArch()L2290–L2351按WALLS/WINS/DOORS重建墙体支持剖切墙高度、玻璃窗、可开关的门同时把墙体与门写入colliders数组供漫游模式做碰撞检测。主循环L2651–L2665统一处理补间动画、飞行动画、环绕控制或漫游步进、门的缓动开合最后渲染场景。日照时间滑块通过applyLight()改变太阳方位角、色温与强度夜景模式切换室内灯具见 L2395–L2408。漫游模式桌面端用指针锁定 WASD触屏则退化为虚拟摇杆 拖动转向L2532–L2616。2D 与 3D 的桥共享 state 签名 diff单文件架构最巧妙的地方在于两个世界如何同步它们共用同一个state和ui对象没有任何「2D 数据 / 3D 数据」的副本单位换算2D 全程用毫米3D 侧用wx/wz/M三个函数换算成米并把户型中心移到世界原点L1524–L1525增量重建sync()L2377–L2383把房间/墙体/家具各自JSON.stringify后与上次签名比对谁变了才重建谁的 Group避免每帧重跑数百个几何体3D 中拖家具走的是与 2D 同一套snapMove()吸附逻辑松手后commit()进同一个撤销栈——所以在 3D 里摆的家具CtrlZ同样能撤掉模块边界3D 模块只向外暴露window.View3Denter/exit/sync/shot/groundAt/flyToRoom见 L26712D 侧的顶栏按钮通过这个接口驱动 3D进出 3D 的仪式感切到 3D 时透视相机先摆到与当前 2D 视口完全重合的正俯视位姿planPose()L2415–L2419交叉淡入后镜头沿球坐标弧线倾斜、墙体从地面「长」起来、家具随后立起enter()L2449–L2468返回 2D 则反向压平淡出。切视图入口在 L1420–L1429藏在细节里的工程化单文件并不意味着糙。翻源码能看到不少面向真实用户的设计三语界面tr(zh, en)双参函数 一张由 OpenCC 生成的简繁对照表L346–L384静态文案靠 HTML 上的data-en属性切换用户改过的名字原样保留响应式CSS 媒体查询把窄屏侧栏变成抽屉L204–L215触屏设备加大点击区、用 Pointer 事件替代 HTML5 拖放iPad 上后者不可靠见 L1337 注释导出2D 导出 PNG 是把 SVG 克隆 → 改 viewBox → 序列化成 Image 再画进 CanvasL1389–L14063D 截图直接取renderer.domElement.toDataURLL2667方案 JSON 导入导出让作品可以分享导出图片的 PNG 路径还会自动判断当前处于 2D 还是 3D调用对应实现换成自己的户型改数据就行想把自己的户型搬进来只需替换文件头部那几组常量README 的「自定义户型」一节也有说明改WALLS/WINS按毫米坐标写墙体与窗洞改ROOMS房间多边形与名称改LIB/buildFurniture()自定义家具库与 3D 模型数据一改2D 渲染、面积统计、地面材料估价、3D 建筑全部自动跟着变——这正是「单一数据源」架构的回报。小结floorplan-3d 证明了单文件前端可以有多完整分层靠注释区块而非文件夹CSS → 骨架 → 2D 经典脚本 → 3D 模块职责边界清晰单一 state 是灵魂2D 的 SVG 重绘、3D 的签名 diff、撤销栈、localStorage 全部围绕它展开字符串模板渲染 程序化贴图没有 DOM 库、没有图片资源依然做出 60 余种精细家具module 脚本 window 桥在单文件里优雅地隔开了 2D 与 three.js 两个世界 项目资料README.md中文、README.en.md英文、LICENSEMIT 协议【免费下载链接】floorplan-3d项目地址: https://gitcode.com/gh_mirrors/fl/floorplan-3d创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考