Vue3 + Cesium.js 实战:手把手教你从零搭建一个3D楼盘分户管理系统
Vue3 Cesium.js 实战从零构建3D楼盘分户管理系统的完整指南在房地产数字化浪潮中3D可视化技术正成为提升楼盘展示和管理效率的关键工具。本文将带您完整实现一个基于Vue3和Cesium.js的楼盘分户管理系统涵盖从地图初始化到业主信息管理的全流程开发。1. 项目基础搭建与环境配置1.1 初始化Vue3项目首先创建一个新的Vue3项目npm init vuelatest cesium-house-management cd cesium-house-management npm install安装必要的依赖npm install cesium cesium/engine turf/turf element-plus1.2 Cesium.js集成配置在vite.config.js中添加Cesium配置import { defineConfig } from vite import vue from vitejs/plugin-vue import cesium from vite-plugin-cesium export default defineConfig({ plugins: [vue(), cesium()] })创建Cesium初始化工具文件src/utils/cesiumInit.jsimport { Ion } from cesium/engine export const initViewer (containerId) { Ion.defaultAccessToken 您的Cesium Ion访问令牌 return new Cesium.Viewer(containerId, { timeline: false, animation: false, selectionIndicator: false, infoBox: false, baseLayerPicker: false, terrainProvider: Cesium.createWorldTerrain() }) }2. 核心功能模块实现2.1 3D地图初始化与建筑加载创建地图组件src/components/CesiumMap.vuetemplate div idcesiumContainer/div /template script setup import { onMounted } from vue import { initViewer } from ../utils/cesiumInit let viewer onMounted(() { viewer initViewer(cesiumContainer) // 加载3D建筑模型 const tileset viewer.scene.primitives.add( new Cesium.Cesium3DTileset({ url: /path/to/your/tileset.json, maximumScreenSpaceError: 2, dynamicScreenSpaceError: true }) ) viewer.zoomTo(tileset) }) /script style scoped #cesiumContainer { width: 100%; height: 100vh; } /style2.2 区域绘制功能实现创建绘图工具src/utils/drawTools.jsexport const startDrawingPolygon (viewer, callback) { let activeShapePoints [] let activeShape let floatingPoint const handler new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) handler.setInputAction((movement) { const earthPosition viewer.scene.pickPosition(movement.position) if (!earthPosition) return if (activeShapePoints.length 0) { floatingPoint createPoint(viewer, earthPosition) activeShapePoints.push(earthPosition) activeShape createPolygon(viewer, activeShapePoints) } activeShapePoints.push(earthPosition) updatePolygon(viewer, activeShape, activeShapePoints) }, Cesium.ScreenSpaceEventType.LEFT_CLICK) handler.setInputAction((movement) { if (activeShapePoints.length 1) return const earthPosition viewer.scene.pickPosition(movement.endPosition) if (!earthPosition) return floatingPoint.position.setValue(earthPosition) activeShapePoints.pop() activeShapePoints.push(earthPosition) updatePolygon(viewer, activeShape, activeShapePoints) }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) handler.setInputAction(() { if (activeShapePoints.length 3) return handler.destroy() activeShapePoints.pop() callback(activeShapePoints) }, Cesium.ScreenSpaceEventType.RIGHT_CLICK) } const createPoint (viewer, position) { return viewer.entities.add({ position, point: { color: Cesium.Color.WHITE, pixelSize: 5, outlineColor: Cesium.Color.BLACK, outlineWidth: 2 } }) } const createPolygon (viewer, positions) { return viewer.entities.add({ polygon: { hierarchy: new Cesium.PolygonHierarchy(positions), material: Cesium.Color.GREEN.withAlpha(0.5), outline: true, outlineColor: Cesium.Color.BLACK } }) } const updatePolygon (viewer, polygon, positions) { polygon.polygon.hierarchy new Cesium.PolygonHierarchy(positions) }2.3 户型切分算法实现使用Turf.js实现多边形分割import * as turf from turf/turf export const splitPolygon (polygonCoords, splitLineCoords) { const polygon turf.polygon([polygonCoords]) const line turf.lineString(splitLineCoords) try { const splitPolygons turf.polygonSplit(polygon, line) return splitPolygons } catch (error) { console.error(分割失败:, error) return null } }3. 高级功能开发3.1 楼房分层可视化实现楼层分层的核心代码export const createBuildingFloors (viewer, basePolygon, floorHeights) { const floors [] const floorCount floorHeights.length - 1 for (let i 0; i floorCount; i) { const floorHeight floorHeights[i] const nextFloorHeight floorHeights[i 1] const floor viewer.entities.add({ polygon: { hierarchy: basePolygon, height: floorHeight, extrudedHeight: nextFloorHeight, material: Cesium.Color.fromRandom({ red: 0.1, green: 0.1, blue: 0.8, alpha: 0.5 }), outline: true, outlineColor: Cesium.Color.BLACK } }) floors.push(floor) } return floors }3.2 业主信息管理集成创建业主信息组件src/components/OwnerInfo.vuetemplate div classowner-info el-dialog v-modeldialogVisible title业主信息 el-form :modelownerForm label-width120px el-form-item label业主姓名 el-input v-modelownerForm.name / /el-form-item el-form-item label联系方式 el-input v-modelownerForm.phone / /el-form-item el-form-item label房屋面积 el-input v-modelownerForm.area suffixm² / /el-form-item el-form-item label户型图 el-upload action/api/upload el-button typeprimary上传户型图/el-button /el-upload /el-form-item /el-form /el-dialog /div /template script setup import { ref } from vue const dialogVisible ref(false) const ownerForm ref({ name: , phone: , area: , image: }) const showInfo (unitData) { ownerForm.value { ...unitData } dialogVisible.value true } defineExpose({ showInfo }) /script4. 性能优化与最佳实践4.1 3D渲染性能优化// 使用实例化渲染提高性能 export const createInstancedBuildings (viewer, polygons, heights) { const instances polygons.map((polygon, index) { return new Cesium.GeometryInstance({ geometry: new Cesium.PolygonGeometry({ polygonHierarchy: new Cesium.PolygonHierarchy(polygon), height: heights[index].min, extrudedHeight: heights[index].max }), attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor( Cesium.Color.fromRandom({ alpha: 0.7 }) ) } }) }) viewer.scene.primitives.add( new Cesium.Primitive({ geometryInstances: instances, appearance: new Cesium.PerInstanceColorAppearance({ flat: true, translucent: true }), asynchronous: false }) ) }4.2 内存管理最佳实践// 清理不再使用的实体 export const cleanupEntities (viewer, entitiesToKeep []) { const allEntities viewer.entities.values const entitiesToRemove [] for (let i 0; i allEntities.length; i) { if (!entitiesToKeep.includes(allEntities[i])) { entitiesToRemove.push(allEntities[i]) } } // 倒序删除避免索引问题 for (let i entitiesToRemove.length - 1; i 0; i--) { viewer.entities.remove(entitiesToRemove[i]) } }5. 项目部署与上线5.1 生产环境配置创建src/config.jsexport default { cesium: { token: import.meta.env.VITE_CESIUM_TOKEN, tilesetUrl: import.meta.env.VITE_TILESET_URL }, api: { baseUrl: import.meta.env.VITE_API_BASE_URL } }5.2 Docker部署配置创建DockerfileFROM node:16 as build-stage WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:alpine as production-stage COPY --frombuild-stage /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD [nginx, -g, daemon off;]创建nginx.confserver { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /tiles { alias /data/tiles; } }6. 实际应用案例与扩展在完成基础功能后可以考虑以下扩展方向VR/AR集成使用WebXR API实现虚拟看房体验大数据可视化集成社区人口统计、设施使用等数据分析IoT设备对接连接智能家居设备实现远程控制移动端适配优化PWA体验实现离线使用// WebXR集成示例 export const initXR async (viewer) { if (!navigator.xr) { console.warn(WebXR not supported) return } try { const xrSession await navigator.xr.requestSession(immersive-vr) viewer.scene.useWebXR true viewer.scene.requestXRSession(xrSession) } catch (error) { console.error(XR session failed:, error) } }通过本项目的完整实现开发者可以掌握Vue3与Cesium.js结合开发复杂3D可视化系统的全流程技能为房地产、智慧园区等领域提供创新的数字化解决方案。