【VUE】Vue3 绘制 3D 蓝图利器 Grid Plan
什么是Grid Plan
Grid Plan 是一个轻量级 Vue3 组件,用来实时绘制并交互式管理“网格蓝图”——从房间、机柜到数据中心,都能秒级可视化。它可用于创建房间、数据中心、机架等的蓝图,具备放置、调整大小或删除组件,以及自定义蓝图外观等功能。
优势
Grid - plan 作为一款用于创建蓝图的 Vue3 组件,具有以下优势:
1、安装与使用简便:
可通过 npm 轻松安装,命令为 “npm i grid - plan”。并且可以在 main.js 中全局声明组件,也可直接在 Vue 文件中导入使用,对于熟悉 Vue 框架的开发者来说,上手难度较低。
2、高度可定制性:
组件类型自定义:通过 “availableTypes” 属性,能够指定可放置在蓝图上的组件类型,比如可以定义服务器、电源、显示器等多种组件类型,满足不同场景的蓝图绘制需求。
外观配置灵活:“config” 属性用于自定义外观,用户可以根据自己的喜好和实际需求,对蓝图的外观进行个性化设置,使蓝图更加美观和符合特定的风格要求。
读写状态可控:“readonly” 属性为布尔值,若设为 “true”,蓝图将为只读状态,这在一些需要展示蓝图但不允许用户进行修改的场景下非常有用,同时也可以通过设置为 “false” 来实现可编辑功能,灵活控制蓝图的使用状态。
3、功能丰富实用:
组件操作便捷:支持放置、调整大小或删除组件等操作,能够方便地对蓝图上的各种元素进行管理和布局调整。例如,可以根据实际空间规划,轻松地调整服务器组件的位置和大小。
事件处理灵活:可以通过定义相关函数来处理各种事件,如 “selectType”“change” 等函数,能够实现与用户交互的功能,增强了蓝图的交互性和用户体验。
数据管理方便:“placedItems” 属性表示已放置在蓝图上的组件,开发人员可以方便地获取和管理这些组件的数据,有利于对整个蓝图的状态进行跟踪和控制。
开发友好:基于 Vue3 框架开发,利用了 Vue3 的响应式特性和组件化架构,使得开发过程更加高效和清晰,便于开发者进行维护和扩展。对于 Vue 开发者来说,不需要学习全新的技术体系,就能够快速上手进行 Grid - plan 组件的集成和二次开发。
亮点
亮点 | 一句话说明 |
---|---|
2D/3D 一键切换 | 同一套数据,实时生成可旋转、缩放的 3D 视图 |
完全可插拔 | 8 个插槽 + BEM 类名,样式和 UI 想怎么改就怎么改 |
事件驱动 | 增删改选全部通过事件抛回,业务逻辑零侵入 |
TypeScript 零配置 | 所有类型开箱即用,IDE 自动补全 |
实现代码
首先确保已安装该组件:
npm i grid-plan
基础房间蓝图实现代码:
<template><div class="room-blueprint-container"><h2>房间蓝图设计工具</h2><!-- 工具栏 --><div class="toolbar mb-4 p-3 bg-gray-100 rounded-lg"><button v-for="type in availableTypes" :key="type.id"@click="selectType(type.id)":class="['px-3 py-1 mr-2 rounded', selectedTypeId === type.id ? 'bg-blue-500 text-white' : 'bg-gray-200']">{{ type.name }}</button><button @click="clearSelection" class="px-3 py-1 bg-red-200 rounded ml-auto">清除选择</button></div><!-- Grid-plan 蓝图组件 --><grid-plan:available-types="availableTypes":placed-items="placedItems":readonly="false":config="gridConfig"@change="handleChange"@select="handleSelect"class="border-2 border-gray-300 rounded-lg"/><!-- 属性编辑面板 --><div v-if="selectedItem" class="properties-panel mt-4 p-3 bg-gray-50 rounded-lg"><h3>编辑属性</h3><div class="form-group"><label>名称:</label><input type="text" v-model="selectedItem.name" class="border rounded p-1 w-full"></div><div class="form-group"><label>宽度:</label><input type="number" v-model="selectedItem.width" class="border rounded p-1 w-full"min="1"></div><div class="form-group"><label>高度:</label><input type="number" v-model="selectedItem.height" class="border rounded p-1 w-full"min="1"></div><button @click="removeSelected" class="mt-2 px-3 py-1 bg-red-500 text-white rounded">删除</button></div></div>
</template><script setup>
import { ref, watch } from 'vue';
import GridPlan from 'grid-plan';// 定义可用组件类型(房间元素)
const availableTypes = ref([{ id: 'wall', name: '墙体', color: '#333333' },{ id: 'door', name: '门', color: '#8B4513' },{ id: 'window', name: '窗户', color: '#87CEEB' },{ id: 'bed', name: '床', color: '#FFB6C1' },{ id: 'table', name: '桌子', color: '#DEB887' },{ id: 'chair', name: '椅子', color: '#D2B48C' }
]);// 已放置的元素
const placedItems = ref([// 初始房间框架(墙体){ id: 'wall1', type: 'wall', x: 0, y: 0, width: 10, height: 1 },{ id: 'wall2', type: 'wall', x: 0, y: 0, width: 1, height: 8 },{ id: 'wall3', type: 'wall', x: 0, y: 7, width: 10, height: 1 },{ id: 'wall4', type: 'wall', x: 9, y: 0, width: 1, height: 6 },// 初始门和窗{ id: 'door1', type: 'door', x: 7, y: 7, width: 2, height: 1 },{ id: 'window1', type: 'window', x: 3, y: 0, width: 2, height: 1 }
]);// 网格配置
const gridConfig = ref({gridSize: 50, // 每个网格单元的像素大小showGrid: true, // 显示网格线backgroundColor: '#F5F5F5', // 背景颜色gridColor: '#E0E0E0' // 网格线颜色
});// 选中的元素
const selectedTypeId = ref(null);
const selectedItem = ref(null);// 选择元素类型
const selectType = (typeId) => {selectedTypeId.value = typeId;
};// 清除选择
const clearSelection = () => {selectedTypeId.value = null;selectedItem.value = null;
};// 处理蓝图变化
const handleChange = (items) => {placedItems.value = items;
};// 处理元素选择
const handleSelect = (item) => {selectedItem.value = item;selectedTypeId.value = item?.type || null;
};// 删除选中元素
const removeSelected = () => {if (selectedItem.value) {placedItems.value = placedItems.value.filter(item => item.id !== selectedItem.value.id);selectedItem.value = null;}
};// 监听选中元素变化,自动更新蓝图
watch(selectedItem, (newVal) => {if (newVal) {// 触发蓝图更新placedItems.value = [...placedItems.value];}
});
</script><style scoped>
.room-blueprint-container {max-width: 1200px;margin: 20px auto;padding: 0 20px;
}.toolbar {display: flex;flex-wrap: wrap;align-items: center;
}.properties-panel {max-width: 300px;
}.form-group {margin-bottom: 10px;
}
</style>
实现说明:
元素库:预设了墙体、门、窗、床、桌子、椅子等常用房间元素
交互操作:
点击工具栏按钮选择元素类型
在蓝图上点击放置元素
拖拽调整元素位置
拖动边缘调整元素大小
选中元素后可编辑名称、尺寸或删除
视觉配置:通过gridConfig
设置网格大小、背景色等外观属性
核心 API 速查表
availableTypes:可放置的组件类型清单(含图标、颜色等)
placedItems:已摆放在蓝图上的组件实例(坐标 + 尺寸)
config.showGrid3d:3d开关,是否启用 3D 视图
config.grid3dPosition:3D 视图位于 2D 网格的上方或下方
事件:@change
/ @delete
/ @select
/ @created
组件增删改选时触发
嵌入后台
全局注册(main.js)
import { GridPlan } from 'grid-plan'
app.component('GridPlan', GridPlan)
业务页面
<template><GridPlan:availableTypes="types":placedItems="layout":config="{ showGrid3d: true, grid3dPosition: 'top' }"@change="saveLayout"@delete="removeDevice"><!-- 自定义清单 --><template #inventory="{ item, deleteItem }"><DeviceCard :device="item" @remove="deleteItem" /></template></GridPlan>
</template><script setup lang="ts">
import type { GridPlanItem, GridPlanItemType } from 'grid-plan'const types = ref<GridPlanItemType[]>([{ typeId: 1, description: 'Dell R750', color: '#007DB8', icon: 'server' },{ typeId: 2, description: 'APC UPS', color: '#FF6F00', icon: 'power' }
])const layout = ref<GridPlanItem[]>([]) // 从接口拉取
const saveLayout = (item: GridPlanItem) => api.save(item)
const removeDevice = (item: GridPlanItem) => api.delete(item.id)
</script>
3D 视图应用
实时同步
2D 改尺寸 → 3D 立即拉伸;3D 拖拽 → 2D 坐标实时变
零额外建模
不需要 glTF/obj,任何矩形组件自动生成立方体
性能优势
1000+ 方块 60 FPS,WebGL 局部更新
旋转缩放
鼠标拖拽旋转 / 滚轮缩放 / 触控板双指
总结
从 Excel 到 3D,只需一个 <GridPlan>
标签。
- 可以添加更多家具类型(如衣柜、书架等)
- 增加保存 / 加载功能,将蓝图数据保存到本地存储
- 实现缩放和平移功能,方便编辑大尺寸房间
- 添加尺寸标注功能,显示实际长度(如米)
- 增加 3D 预览切换功能(需结合其他 3D 库)
使用时,你可以根据实际需求调整availableTypes
中的元素类型和gridConfig
中的视觉参数,创建符合自己需求的房间蓝图工具。
此外,可能还有其他软件或工具也具备类似创建 3D 蓝图的功能,如 Floorplanner 可轻松绘制和规划各种空间,并生成实时 3D 视图;QuickPlan 3D 能快速生成平面图的 3D 表示,并可调整墙的厚度、选择门窗类型等。