import { BimfaceSDKLoader, BimfaceSDKLoaderConfig, Glodon } from 'bimfacesdkloader'; import eventBus from './eventBus'; import * as echarts from 'echarts'; import * as $ from 'jquery'; import loadVueComponent from './loadVueComponent'; let app, viewer, drawableContainer, clickHandler, extObjMng, videoManager, anchorMng; // 加载模型 const loadModel = (viewToken, domElement, callback) => { const config = new BimfaceSDKLoaderConfig(); config.viewToken = viewToken; BimfaceSDKLoader.load(config).then((viewMetaData) => { if (viewMetaData.viewType == "3DView") { // ======== 判断是否为3D模型 ======== // 获取DOM元素 let webAppConfig = new Glodon.Bimface.Application.WebApplication3DConfig(); webAppConfig.domElement = domElement; // 允许爆炸 webAppConfig.enableExplosion = true; //允许材质替换 webAppConfig.enableReplaceMaterial = true; // 创建WebApplication app = new Glodon.Bimface.Application.WebApplication3D(webAppConfig); // 从WebApplication获取viewer3D对象 viewer = app.getViewer(); // 添加待显示的模型 viewer.loadModel({ // 待加载模型的浏览凭证 viewToken: viewToken, }); viewer.addEventListener(Glodon.Bimface.Viewer.Viewer3DEvent.ViewAdded, () => { let drawableContainerConfig = new Glodon.Bimface.Plugins.Drawable.DrawableContainerConfig(); drawableContainerConfig.viewer = viewer; drawableContainer = new Glodon.Bimface.Plugins.Drawable.DrawableContainer(drawableContainerConfig); extObjMng = new Glodon.Bimface.Plugins.ExternalObject.ExternalObjectManager(viewer); let videoManagerConfig = new Glodon.Bimface.Plugins.Videos.VideoManagerConfig() videoManagerConfig.viewer = viewer; videoManager = new Glodon.Bimface.Plugins.Videos.VideoManager(videoManagerConfig); let anchorMngConfig = new Glodon.Bimface.Plugins.Anchor.AnchorManagerConfig(); anchorMngConfig.viewer = viewer; anchorMng = new Glodon.Bimface.Plugins.Anchor.AnchorManager(anchorMngConfig); if (callback && typeof callback == "function") callback(); }) window.viewer = viewer; } }); } // 恢复全部状态 const resetStatus = () => { if (!viewer) return; floorExploded && viewer.getModel().clearFloorExplosion(); drawableContainer && drawableContainer.clear(); progressAnimation && cancelAnimationFrame(progressAnimation); elevationAnimation && cancelAnimationFrame(elevationAnimation); sectionPlane && sectionPlane.exit(); extObjMng && extObjMng.clear(); videoManager && videoManager.clear(); anchorMng && anchorMng.clear(); viewer.showAllComponents(); viewer.clearAllRooms(); viewer.restoreAllDefault(); viewer.getModel().clearAllBlinkComponents(); viewer.getModel().clearGlowEffect(); viewer.render(); onClick(() => { }); eventBus.trigger('reset'); } // 设置相机视角 const setCameraStatus = (status) => { return new Promise((resolve) => { viewer.setCameraStatus(status, resolve); }); } // 绑定模型点击事件 const onClick = (fn) => { if (clickHandler) { viewer.removeEventListener(Glodon.Bimface.Viewer.Viewer3DEvent.MouseClicked, clickHandler); } clickHandler = fn; viewer.addEventListener(Glodon.Bimface.Viewer.Viewer3DEvent.MouseClicked, clickHandler); } // 添加引线标签 // 引线标签Demo https://bimface.com/developer-jsdemo#830 const addLeadLabel = (config, onClick) => { let leadLabelConfig = new Glodon.Bimface.Plugins.Drawable.LeadLabelConfig(); let leadLabel = new Glodon.Bimface.Plugins.Drawable.LeadLabel({ ...leadLabelConfig, ...config }); onClick && leadLabel.onClick(onClick); drawableContainer.addItem(leadLabel); } // 添加自定义标签 // 自定义标签Demo https://bimface.com/developer-jsdemo#828 const addCustomItem = (config, onClick, callback) => { let customItemConfig = new Glodon.Bimface.Plugins.Drawable.CustomItemConfig(); let customItem = new Glodon.Bimface.Plugins.Drawable.CustomItem({ ...customItemConfig, ...config }); onClick && customItem.onClick(onClick); drawableContainer.addItem(customItem); if (callback && typeof callback == "function") callback(customItem); } // 删除自定义标签通过id const deleteCustomItemById = (id) => { drawableContainer.removeItemById(id); } // 显示自定义标签通过ids const showCustomItemById = (ids) => { drawableContainer.showItemsById(ids); } // 隐藏自定义标签通过ids const hideCustomItemById = (ids) => { drawableContainer.hideItemsById(ids); } // 添加图片标签 const addImage = (config, onClick) => { let imageConfig = new Glodon.Bimface.Plugins.Drawable.ImageConfig(); let image = new Glodon.Bimface.Plugins.Drawable.Image({ ...imageConfig, ...config }); onClick && image.onClick(onClick); drawableContainer.addItem(image); } // 封装自定义标签的容器 const getCustomContainer = () => { const setCss = (dom, css) => { Object.entries(css).forEach(([key, value]) => { dom.style[key] = value; }) } const div = document.createElement('div'); setCss(div, { background: '#fff', borderRadius: '5px', border: '2px solid rgb(31, 147, 255)', position: 'relative', boxShadow: '0 0 10px #333' }); const leadLine = document.createElement('div'); setCss(leadLine, { background: 'rgb(31, 147, 255)', width: '50px', height: '1px', position: 'absolute', top: '20px', left: '-50px', borderTop: '1px solid rgb(31, 147, 255)', borderBottom: '1px solid rgb(31, 147, 255)', }); const leadLine2 = document.createElement('div'); setCss(leadLine2, { background: 'rgb(31, 147, 255)', width: '50px', height: '1px', position: 'absolute', top: '32px', left: '-96px', border: '1px solid rgb(31, 147, 255)', borderRight: 'none', transform: 'rotate(-30deg)', borderRadius: '5px 0 0 5px' }); div.appendChild(leadLine); div.appendChild(leadLine2); return div; } // 隐藏外墙 const hideOutWall = () => { viewer.getModel().hideComponentsByObjectData([{ categoryId: '-2000170' }, { categoryId: '-2000171' }, { categoryId: '-2000151' }, { categoryId: '-2000014' }, { familyType: 'Exterior - Insulation on Masonry' }, { familyType: 'Generic - 200mm' }]); } //设置构建透明根据构建id const setTransparentComponentsById = (ids) => { viewer.transparentComponentsById(ids); viewer.render(); } //取消构建设置半透明状态通过构建id const setOpaqueComponentsById = (ids) => { viewer.transparentComponentsById(ids); viewer.render(); } // 发光效果 // 发光效果Demo https://bimface.com/developer-jsdemo#1114 const glowSelection = () => { resetStatus(); viewer.enableGlowEffect(true); onClick((data) => { viewer.getModel().clearGlowEffect(); if (viewer.getModel().getSelectedComponents().length > 0) { viewer.getModel().setGlowEffectById([data.objectId], { type: "outline", color: new Glodon.Web.Graphics.Color(255, 255, 190, 1), intensity: 0.3, spread: 4 }); } viewer.render(); }) } // 闪烁效果 // 闪烁效果Demo https://bimface.com/developer-jsdemo#993 const blinkSelection = () => { resetStatus(); viewer.enableBlinkComponents(true); onClick((data) => { viewer.getModel().clearAllBlinkComponents(); if (viewer.getModel().getSelectedComponents().length > 0) { viewer.getModel().addBlinkComponentsById([data.objectId]); } viewer.render(); }) } // 锚点效果 // 锚点效果Demo https://bimface.com/developer-jsdemo#1117 const anchorSelection = () => { resetStatus(); onClick((data) => { anchorMng.clear(); if (viewer.getModel().getSelectedComponents().length > 0) { let prismPointConfig = new Glodon.Bimface.Plugins.Anchor.PrismPointConfig(); prismPointConfig.position = data.worldPosition; const boundingBox = viewer.getModel().getBoundingBoxById("140056"); if (boundingBox) { prismPointConfig.position.z = boundingBox.max.z; } prismPointConfig.duration = 1500; prismPointConfig.size = 3000; const prismPoint = new Glodon.Bimface.Plugins.Anchor.PrismPoint(prismPointConfig); anchorMng.addItem(prismPoint); } }) } // 楼层爆炸 // 楼层爆炸Demo https://bimface.com/developer-jsdemo#1012 let floorList; let floorExploded = false; const floorExplosion = ({ direction, list, ratio }) => { floorExploded = true; hideOutWall(); const execute = () => { viewer.getModel().setFloorExplosion(ratio || 3, list || floorList, direction || { x: 0, y: 0, z: 1 }); viewer.render(); } if (!floorList) { viewer.getFloors(function (data) { if (!data) { console.log('No floor data.'); return; } floorList = data.map(item => item.id); execute(); }); } else { execute(); } } // 通过楼层爆炸展示对应楼层内景 const showFloor = async () => { resetStatus(); viewer.getModel().hideComponentsByObjectData([{ familyType: 'Furred Ceiling' }, { familyType: '600 x 600mm Grid' }]) floorExplosion({ list: ['694', '136342'], ratio: 5 }); await setCameraStatus({ "name": "persp", "position": { "x": -18581.90102579501, "y": -43385.96948291367, "z": 48259.49574346754 }, "target": { "x": 183683.96553301584, "y": 184022.91100671078, "z": -138602.42728235415 }, "up": { "x": 0.34773591007493626, "y": 0.39095752305370535, "z": 0.8521924383682755 }, "near": 30.987299999188124, "far": 225023.77345792603, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.7750257997936016, "coordinateSystem": "world" }); } // 楼层斜向爆炸 展示多个楼层内景 const showFloorBias = async () => { resetStatus(); viewer.getModel().hideComponentsByObjectData([{ familyType: 'Furred Ceiling' }, { familyType: '600 x 600mm Grid' }]) floorExplosion({ direction: { x: -1, y: 1, z: 1 }, ratio: 5 }); await setCameraStatus({ "name": "persp", "position": { "x": 11240.411621892461, "y": -102529.34741011732, "z": 65558.92527280154 }, "target": { "x": 43243.82648777891, "y": 220893.25417478292, "z": -82485.86591627813 }, "up": { "x": 0.04082046922112373, "y": 0.41252263958919705, "z": 0.9100322857563509 }, "near": 25552.128419500546, "far": 204849.5409590415, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.7750257997936016, "coordinateSystem": "world" }); addLeadLabel({ worldPosition: { x: 32990.244621434686, y: 7855.8522796793095, z: 33122.67578124999 }, text: '3F: 研发中心' }); addLeadLabel({ worldPosition: { x: 43951.33038984035, y: -3319.9946107938667, z: 17299.43750000001 }, text: '2F: 商务中心' }); } // 剖切模拟施工进度 // 剖切面Demo https://bimface.com/developer-jsdemo#1108 let sectionPlane = null; let originPt = { x: 0, y: 0, z: 7600 }; let planeDirection = { x: 0, y: 0, z: 1 }; let sectionPlaneOffset = 500; let progressAnimation = null; const createSectionPlane = () => { if (sectionPlane) { return; } let sectionPlaneConfig = new Glodon.Bimface.Plugins.Section.SectionPlaneConfig(); sectionPlaneConfig.viewer = viewer; sectionPlane = new Glodon.Bimface.Plugins.Section.SectionPlane(sectionPlaneConfig); sectionPlane.setPlane(Glodon.Bimface.Plugins.Section.SectionPlanePlane.Z); sectionPlane.setDirection(Glodon.Bimface.Plugins.Section.SectionPlaneDirection.Forward); sectionPlane.setPositionByPlane(originPt, planeDirection, sectionPlaneOffset); sectionPlane.setObjectsByObjectData([ { categoryId: "-2000011", family: "基本墙" }, { categoryId: "-2001330" } ]); sectionPlane.hidePlane(); } const progressMonitor = () => { resetStatus(); viewer.getModel().hideComponentsByObjectData([ { levelName: "Roof" }, { levelName: "Parapet" }, { levelName: "03 - Floor", categoryId: "-2000038" }, { categoryId: "-2000023" } ]); setCameraStatus({ "name": "persp", "position": { "x": -30219.946765163415, "y": -45491.65416486451, "z": 29660.465140231066 }, "target": { "x": 207832.38340026487, "y": 170233.69288006236, "z": -126343.72635548069 }, "up": { "x": 0.3236896665312058, "y": 0.2933266544203183, "z": 0.8995468156730366 }, "fov": 45, "zoom": 1, "version": 1, "coordinateSystem": "world" }); sectionPlane || createSectionPlane(); progressAnimation && cancelAnimationFrame(progressAnimation); const animate = () => { progressAnimation = requestAnimationFrame(animate); sectionPlaneOffset += 100; if (sectionPlaneOffset > 3500) { sectionPlaneOffset = 500; } sectionPlane.setPositionByPlane(originPt, planeDirection, sectionPlaneOffset); viewer.render(); } animate(); } // 获取房间列表 let roomList; const getRoomList = async () => { return new Promise((resolve) => { if (roomList) { resolve(roomList); } else { viewer.getModel().getAreas((data) => { const { rooms } = data[2]; roomList = rooms; resolve(roomList); }) } }) } // 显示房间 const showRooms = async () => { resetStatus(); showFloor(); const rooms = await getRoomList(); rooms.forEach((roomData) => { const { boundary, id } = roomData; viewer.createRoom(boundary, 2000, id); }) viewer.render(); } // 通过不同颜色显示房间温度 // 创建房间 https://bimface.com/developer-jsdemo#1032 const showRoomTemperature = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const color0 = new Glodon.Web.Graphics.Color(0, 255, 0, 0.2); const color1 = new Glodon.Web.Graphics.Color(255, 255, 0, 0.2); const color2 = new Glodon.Web.Graphics.Color(255, 0, 0, 0.2); const colorList = [color0, color1, color2]; rooms.forEach((roomData) => { const { boundary, id } = roomData; const color = colorList[Math.floor(Math.random() * 3)]; viewer.createRoom(boundary, 2000, id, color, color); }) viewer.render(); onClick((data) => { drawableContainer && drawableContainer.clear(); const { worldPosition } = data; addLeadLabel({ worldPosition, text: '房间温度:26 ℃', }); }) } // 显示房间人流量 const showRoomPerson = async () => { await showRoomTemperature(); onClick((data) => { drawableContainer && drawableContainer.clear(); const { worldPosition } = data; addLeadLabel({ worldPosition, text: '当前人数:12', }); }) } // 通过不同颜色表示会议室预定情况 const showMeetingRoom = async () => { const meetingRoomIndex = [1, 4, 11, 19]; resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const color0 = new Glodon.Web.Graphics.Color(0, 255, 0, 0.2); const color2 = new Glodon.Web.Graphics.Color(255, 0, 0, 0.2); const colorList = [color0, color2]; meetingRoomIndex.forEach((index) => { const roomData = rooms[index]; const { boundary, id } = roomData; const color = colorList[Math.floor(Math.random() * 2)]; viewer.createRoom(boundary, 2000, id, color, color); }) viewer.render(); onClick((data) => { drawableContainer && drawableContainer.clear(); const { worldPosition } = data; addLeadLabel({ worldPosition, text: '302会议室\r\n\r\n预定人: 张三\r\n开始时间: 14:30:00\r\n结束时间: 15:30:00', height: 100 }); }) } // 展示耗电图表 (基于echarts) const showRoomElecChart = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const roomData = rooms[11]; const { boundary, id } = roomData; viewer.createRoom(boundary, 2000, id); viewer.render(); const div = getCustomContainer(); const chartDiv = document.createElement('div'); chartDiv.style.width = '600px'; chartDiv.style.height = '400px'; div.appendChild(chartDiv); addCustomItem({ worldPosition: { x: -6825.774153559483, y: 12198.622346237365, z: 1610.6135227595976 }, content: div, width: 600, height: 400, offsetX: 350, opacity: 1, }); const myChart = echarts.init(chartDiv); // 指定图表的配置项和数据 const option = { title: { text: '用电量分布', }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross' } }, toolbox: { show: true, feature: { saveAsImage: {} } }, xAxis: { type: 'category', boundaryGap: false, // prettier-ignore data: ['00:00', '01:15', '02:30', '03:45', '05:00', '06:15', '07:30', '08:45', '10:00', '11:15', '12:30', '13:45', '15:00', '16:15', '17:30', '18:45', '20:00', '21:15', '22:30', '23:45'] }, yAxis: { type: 'value', axisLabel: { formatter: '{value} W' }, axisPointer: { snap: true } }, visualMap: { show: false, dimension: 0, pieces: [ { lte: 6, color: 'green' }, { gt: 6, lte: 8, color: 'red' }, { gt: 8, lte: 14, color: 'green' }, { gt: 14, lte: 17, color: 'red' }, { gt: 17, color: 'green' } ] }, series: [ { name: 'Electricity', type: 'line', smooth: true, // prettier-ignore data: [300, 280, 250, 260, 270, 300, 550, 500, 400, 390, 380, 390, 400, 500, 600, 750, 800, 700, 600, 400], markArea: { itemStyle: { color: 'rgba(255, 173, 177, 0.4)' }, data: [ [ { name: 'Morning Peak', xAxis: '07:30' }, { xAxis: '10:00' } ], [ { name: 'Evening Peak', xAxis: '17:30' }, { xAxis: '21:15' } ] ] } } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); } // 房间详情,可在自定义标签中加入iframe或自行封装内容进行展示 const showRoomWebsite = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const roomData = rooms[11]; const { boundary, id } = roomData; viewer.createRoom(boundary, 2000, id); viewer.render(); const container = getCustomContainer(); container.style.height = '400px'; const frame = document.createElement('iframe'); frame.src = 'https://bimface.com/'; frame.width = 1190; frame.height = 800; frame.frameBorder = 0; frame.style.transform = 'scale(0.5) translate(-50%, -50%)'; container.appendChild(frame); addCustomItem({ worldPosition: { x: -3160.922652317966, y: -21960.96903375262, z: 29064.386718749993 }, content: container, width: 600, height: 400, offsetX: 350, opacity: 1, }); } // 将Vue Component插入自定义标签 const showSthFromVueComponent = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const roomData = rooms[11]; const { boundary, id } = roomData; viewer.createRoom(boundary, 2000, id); viewer.render(); const container = getCustomContainer(); const div = document.createElement('div'); container.appendChild(div); addCustomItem({ worldPosition: { x: -3160.922652317966, y: -21960.96903375262, z: 29064.386718749993 }, content: container, width: 600, height: 400, offsetX: 350, opacity: 1, }); loadVueComponent(div); } // 通过颜色覆盖显示各楼层用能情况 const showElecArea = async () => { resetStatus(); hideOutWall(); await setCameraStatus({ "name": "persp", "position": { "x": 64840.35214354617, "y": -68511.2525964906, "z": 18326.863098710433 }, "target": { "x": -88901.31809446408, "y": 247356.65487049, "z": -45974.16210384361 }, "up": { "x": -0.07879790601614875, "y": 0.16188945742798264, "z": 0.9836578132567969 }, "near": 30.987299996758253, "far": 205860.68880166902, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.7750257997936016, "coordinateSystem": "world" }); viewer.getModel().overrideComponentsColorByObjectData([{ levelName: '01 - Entry Level' }], new Glodon.Web.Graphics.Color(255, 80, 80, 0.3)); viewer.getModel().overrideComponentsColorByObjectData([{ levelName: '02 - Floor' }], new Glodon.Web.Graphics.Color(255, 255, 80, 0.4)); viewer.getModel().overrideComponentsColorByObjectData([{ levelName: '03 - Floor' }, { levelName: 'Roof' }], new Glodon.Web.Graphics.Color(80, 255, 80, 0.4)); viewer.getModel().overrideComponentsColorByObjectData([{ categoryId: '-2001340' }, { categoryId: '-2001340' }, { categoryId: '-2001360' }], new Glodon.Web.Graphics.Color(150, 150, 150, 1)); viewer.getModel().hideComponentsByObjectData([{ categoryId: '-2001360' }]); addLeadLabel({ worldPosition: { x: 54545.6439964876, y: -21582.57905456956, z: 2000 }, text: '1F能耗:12000kwh', }); addLeadLabel({ worldPosition: { x: 54545.6439964876, y: -21582.57905456956, z: 6000 }, text: '2F能耗:8000kwh', }); addLeadLabel({ worldPosition: { x: 54545.6439964876, y: -21582.57905456956, z: 10000 }, text: '3F能耗:5000kwh', }); } let elevationAnimation; const elevationPositionList = [ { x: 3017.7083642874286, y: -17867.4624208377, z: 0, direction: 1 }, { x: 51137.538027890434, y: -17857.7162947923, z: 7000, direction: -1 } ]; const getElevationBoundary = (position) => { const pt0 = [position.x - 1000, position.y - 1000, position.z]; const pt1 = [position.x - 1000, position.y + 1000, position.z]; const pt2 = [position.x + 1000, position.y + 1000, position.z]; const pt3 = [position.x + 1000, position.y - 1000, position.z]; return viewer.createBoundary([pt0, pt1, pt2, pt3, pt0]); }; // 电梯运行模拟,基于房间 const showElevation = async () => { resetStatus(); await setCameraStatus({ "name": "persp", "position": { "x": 3575.1548085656814, "y": -73273.35356177477, "z": 14980.742555679171 }, "target": { "x": 104565.36505385478, "y": 266903.3467217405, "z": -25323.69883819677 }, "up": { "x": 0.03211961944006518, "y": 0.10818843515523709, "z": 0.993611389098216 }, "near": 30.987299996241962, "far": 197123.90516035885, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.8838992332968236, "coordinateSystem": "world" }); viewer.getModel().overrideComponentsColorByObjectData([{ levelName: '01 - Entry Level' }, { levelName: '02 - Floor' }, { levelName: '03 - Floor' }, { levelName: 'Roof' }, { levelName: 'Parapet' }], new Glodon.Web.Graphics.Color(255, 255, 255, 0.4)); viewer.getModel().restoreComponentsColorByObjectData([{ categoryId: '-2001340' }, { categoryId: '-2001340' }, { categoryId: '-2001360' }]); const animate = () => { viewer.clearAllRooms(); viewer.drawableContainer.clear(); elevationPositionList.forEach((elevationPosition, index) => { elevationPosition.z = elevationPosition.z + 50 * elevationPosition.direction; if (elevationPosition.z < 0) { elevationPosition.z = 0; elevationPosition.direction = 1; } if (elevationPosition.z > 9000) { elevationPosition.z = 9000; elevationPosition.direction = -1; } viewer.createRoom(getElevationBoundary(elevationPosition), 3000, `elevation_${index}`); addLeadLabel({ worldPosition: { ...elevationPosition, z: elevationPosition.z + 3000 }, text: `电梯编号:ELEV_${index + 1}\r\n当前楼层:${Math.floor(elevationPosition.z / 3000) + 1}`, height: 50, id: `elevation_${index}` }); viewer.render(); }); elevationAnimation = requestAnimationFrame(animate); } animate(); } // 视频监控展示 const cameraList = [ { x: -5726.9008039386945, y: -19753.945826512583, z: 30000 }, { x: -6095.6074387552935, y: -3808.760009765628, z: 30000 }, { x: 15496.400137445688, y: -19546.919708011246, z: 30000 }, { x: 15496.400137445688, y: -19546.919708011246, z: 30000 }, { x: 708.6683505627907, y: -7404.043737439564, z: 30000 } ] const showCamera = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); cameraList.forEach((worldPosition, index) => { addImage({ worldPosition, id: `Camera_${index}`, src: '/camera.png', }, () => { if (drawableContainer.getItemById('cameraDetail')) { drawableContainer.removeItemById('cameraDetail'); } const container = getCustomContainer(); container.style.width = '500px'; const div = document.createElement('div'); container.appendChild(div); div.style.paddingTop = '5px'; div.style.background = '#ffffff'; div.innerHTML = `

监控编号:Camera_${index}

`; addCustomItem({ id: 'cameraDetail', content: container, offsetX: 350, offsetY: -50, width: 500, opacity: 1, worldPosition }) }) }) } // 应急逃生模拟 const emergencyPersonList = [ [ { x: 34899.6777375232, y: -17781.80510604883, z: 7650 }, { x: 35413.71163266194, y: -12970.981740591995, z: 7650 }, { x: 4909.007175768803, y: -12818.368805829718, z: 7650 }, { x: 5014.937799840577, y: -3163.5159127192633, z: 7650 }, { x: 2541.930221928287, y: -2977.4966453027077, z: 7650 }, { x: 2731.434117794542, y: -13731.159815044475, z: 3850 } ], [ { x: 3256.5802824349807, y: -18629.367845127417, z: 7650 }, { x: 3237.8045820492266, y: -13102.672257032156, z: 7650 }, { x: 301.0750159020422, y: -13260.941875880095, z: 7650 }, { x: 391.9198447478234, y: -22530.256415770342, z: 5750 }, { x: -822.9792841120037, y: -22508.0637239401, z: 5750 }, { x: -839.347346130226, y: -18167.72168898865, z: 3850 } ], [ { x: -6535.361373622634, y: 7964.572162669435, z: 7650 }, { x: -1526.3852600492792, y: 10405.591448279105, z: 7650 }, { x: 6.437365414656597, y: 8623.094161284605, z: 7650 }, { x: 75.39456886054086, y: -2131.325274325668, z: 7650 }, { x: 2529.2386048856592, y: -1990.0765380885814, z: 7650 }, { x: 2591.5193380935493, y: 8683.088365466227, z: 3850 } ], [ { x: -5304.832644534073, y: -5893.3688449178035, z: 7650 }, { x: 2529.2386048856592, y: -1990.0765380885814, z: 7650 }, { x: 2591.5193380935493, y: 8683.088365466227, z: 3850 } ], [ { x: -4928.4666196471835, y: -15801.417447293017, z: 7650 }, { x: 301.0750159020422, y: -13260.941875880095, z: 7650 }, { x: 391.9198447478234, y: -22530.256415770342, z: 5750 }, { x: -822.9792841120037, y: -22508.0637239401, z: 5750 }, { x: -839.347346130226, y: -18167.72168898865, z: 3850 } ] ]; let personModel; const emergency = async () => { resetStatus(); const loadScript = (url) => { return new Promise((resolve) => { let script = document.createElement("script"); script.type = "text/javascript"; script.onload = function () { resolve(); }; script.src = url; document.head.appendChild(script); }) } if (!window.FBXLoader) { await loadScript("https://static.bimface.com/attach/eb19d39099ef4cf1b53f333a7066694f_inflate.min.js"); await loadScript("https://static.bimface.com/attach/9b1a9a0eab054241974a2b1c436921bc_FBXLoader.js"); } viewer.getModel().hideComponentsByObjectData([{ familyType: 'Furred Ceiling' }, { familyType: '600 x 600mm Grid' }, { levelName: 'Parapet' }, { levelName: 'Roof' }]) await setCameraStatus({ "name": "persp", "position": { "x": -13826.985809631753, "y": -26471.58701973364, "z": 43515.02418597501 }, "target": { "x": 150129.79564140565, "y": 75639.04098523533, "z": -256876.8056661201 }, "up": { "x": 0.7139808607672242, "y": 0.44465327936524296, "z": 0.5408463659929951 }, "near": 30.987299999415217, "far": 166937.83186464157, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.7750257997936016, "coordinateSystem": "world" }); // 火焰效果Demo https://bimface.com/developer-jsdemo#1011 // 火焰对象的插入点 let firePos = { x: 17012.886023946856, y: -18323.941640342815, z: 7599.999999999998 } // 构造火焰效果的配置项 let fireConfig = new Glodon.Bimface.Plugins.ParticleSystem.FireEffectConfig(); // 设置火焰对象的插入点 fireConfig.position = firePos; // 设置火焰对象的viewer对象 fireConfig.viewer = viewer; // 构造火焰对象 const fireEffect = new Glodon.Bimface.Plugins.ParticleSystem.FireEffect(fireConfig); setTimeout(() => { // 喷水效果Demo https://bimface.com/developer-jsdemo#1099 let sprayWaterEffectConfig = new Glodon.Bimface.Plugins.ParticleSystem.SprayWaterEffectConfig(); // 配置Viewer对象、颜色、初始位置、初始俯仰值、初始偏航值、初始半径、初始强度等参数 sprayWaterEffectConfig.viewer = viewer; sprayWaterEffectConfig.color = new Glodon.Web.Graphics.Color(231, 254, 255, 1); sprayWaterEffectConfig.originPosition = { x: 17012.886023946856, y: -31592.259131223247, z: -149.99999999999633 }; sprayWaterEffectConfig.originPitch = 0.15 * Math.PI; sprayWaterEffectConfig.originYaw = 0.5 * Math.PI; sprayWaterEffectConfig.originRadius = 100; sprayWaterEffectConfig.originIntensity = 0.6; // 构造喷水效果对象 const sprayWaterEffect = new Glodon.Bimface.Plugins.ParticleSystem.SprayWaterEffect(sprayWaterEffectConfig); // 设置水花扩散程度 sprayWaterEffect.setSpread(1.1); // 设置粒子大小比例 sprayWaterEffect.setScale(1); // 更新设置 sprayWaterEffect.update(); }, 5000); const getPersonModel = () => { return new Promise((resolve) => { if (personModel) { resolve(personModel.clone()); } else { let loader = new FBXLoader(); loader.load("/Running.fbx", object => { object.rotateX(Math.PI / 2); const group = new THREE.Group(); group.add(object); group.animations = object.animations; personModel = group; resolve(group); }); } }) } const curveIds = []; const curves = []; emergencyPersonList.forEach((list, index) => { // 路径动画Demo https://bimface.com/developer-jsdemo#977 const splineCurve = new Glodon.Bimface.Plugins.Geometry.SplineCurve(list); splineCurve.setType('polyline'); // 曲线动态贴图+辉光效果Demo https://bimface.com/developer-jsdemo#1126 splineCurve.setMap({ src: "https://static-test.bimface.com/attach/3f9b4c5612194a71b0523766840351e6_流线贴图1028-6.png", enableColorOverride: false }, function () { extObjMng.loadObject({ name: `splineCurve_${index}`, object: splineCurve }); let curveId = extObjMng.getObjectIdByName(`splineCurve_${index}`); curveIds.push(curveId); curves.push(splineCurve); if (curveIds.length === emergencyPersonList.length) { let ids = [{ "objectIds": curveIds }]; // 构造辉光效果的配置项 let bloomEffectConfig = new Glodon.Bimface.Plugins.Effect.BloomEffectConfig(); // 设置构件ID数组、强度、扩散程度、viewer等参数 bloomEffectConfig.ids = ids; bloomEffectConfig.intensity = 0.8; bloomEffectConfig.spread = 3; bloomEffectConfig.viewer = viewer; // 构造辉光效果 const bloomEffect = new Glodon.Bimface.Plugins.Effect.BloomEffect(bloomEffectConfig); // 构造曲线动画的配置项 const curveAnimationConfig = new Glodon.Bimface.Plugins.Animation.CurveAnimationConfig(); // 配置Viewer对象、曲线对象、动画时间、动画循环、动画类型等参数 curveAnimationConfig.viewer = viewer; curveAnimationConfig.curves = curves; curveAnimationConfig.time = 5000; curveAnimationConfig.loop = true; curveAnimationConfig.type = "flow"; // 构造曲线动画对象 const curveAnimation = new Glodon.Bimface.Plugins.Animation.CurveAnimation(curveAnimationConfig); curveAnimation.play(); }; const name = `person_${index}`; getPersonModel().then((cModel) => { extObjMng.addObject(name, cModel); extObjMng.translate(extObjMng.getObjectIdByName(name), splineCurve.getPointByParameter(0)); const id = extObjMng.getObjectIdByName(name); extObjMng.scale(id, { x: 10, y: 10, z: 10 }); extObjMng.play(id); let pathAnimationConfig = new Glodon.Bimface.Plugins.Animation.PathAnimationConfig(); pathAnimationConfig.viewer = viewer; pathAnimationConfig.path = splineCurve; pathAnimationConfig.time = 15000; pathAnimationConfig.loop = true; pathAnimationConfig.objectNames = [extObjMng.getObjectIdByName(name)]; pathAnimationConfig.isPitchEnabled = false; pathAnimationConfig.isYawEnabled = true; pathAnimationConfig.originYaw = 0.5 * Math.PI; const pathAnimation = new Glodon.Bimface.Plugins.Animation.PathAnimation(pathAnimationConfig); pathAnimation.play(); }); }); }) viewer.render(); } // 视频播放 // 视频播放Demo https://bimface.com/developer-jsdemo#1133 const showVideo = async () => { resetStatus(); viewer.hideComponentsByObjectData([{ categoryId: '-2001360' }]); await setCameraStatus({ "name": "persp", "position": { "x": -33532.92922171701, "y": 9297.988034476759, "z": 15821.492660198863 }, "target": { "x": 298239.7865031938, "y": 47030.97534564945, "z": -110854.25382006646 }, "up": { "x": 0.3524307768080582, "y": 0.04007852960926472, "z": 0.9349792826703853 }, "near": 30.987300000788515, "far": 231362.1403375684, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.7750257997936016, "coordinateSystem": "world" }); //构造视频配置项 let videoConfig = new Glodon.Bimface.Plugins.Videos.VideoConfig(); // 配置viewer、camera等参数 videoConfig.viewer = viewer; //视频路径,视频格式支持MP4、WebM、Ogg,视频流支持http协议。 videoConfig.src = "https://static.bimface.com/attach/2c44c7fcdd7a48ba933205cec80e97e3_BIMFACE产品介绍.mp4"; videoConfig.plane = { "distance": 20000, "side": 0 }; videoConfig.camera = { "position": { x: -30100, y: 12002.510673476307, z: 9141.613578988039 }, "direction": new THREE.Vector3(1, 0, 0), "horizontalFov": Math.PI * 0.111, "verticalFov": Math.PI * 0.063 }; //设置是否静音、循环播放 videoConfig.mute = false; videoConfig.loop = true; videoConfig.callback = callback; //构造视频对象 const video = new Glodon.Bimface.Plugins.Videos.Video(videoConfig); videoManager.addVideo(video); function callback() { video.play(); } } // 通过电子围墙效果实现LED滚动屏 // 电子围墙Demo https://bimface.com/developer-jsdemo#1135 const showLED = async () => { resetStatus(); viewer.hideComponentsByObjectData([{ categoryId: '-2001360' }]); await setCameraStatus({ "name": "persp", "position": { "x": -33532.92922171701, "y": 9297.988034476759, "z": 15821.492660198863 }, "target": { "x": 298239.7865031938, "y": 47030.97534564945, "z": -110854.25382006646 }, "up": { "x": 0.3524307768080582, "y": 0.04007852960926472, "z": 0.9349792826703853 }, "near": 30.987300000788515, "far": 231362.1403375684, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.7750257997936016, "coordinateSystem": "world" }); // 构造电子围墙效果配置项 let wallEffectConfig = new Glodon.Bimface.Plugins.Animation.WallEffectConfig(); // 配置Viewer对象、方向、持续时间、路径、高度 wallEffectConfig.viewer = viewer; wallEffectConfig.direction = { type: "Tangent", // 运动方式为沿着路径的切线方向 reverse: false // 运动方向默认为逆时针 } wallEffectConfig.duration = 8000; wallEffectConfig.height = 1000; wallEffectConfig.stretch = false; wallEffectConfig.repeat = false; wallEffectConfig.blendingRatio = 1; wallEffectConfig.color = new Glodon.Web.Graphics.Color(0, 0, 0, 1); wallEffectConfig.path = [ { x: -10010, y: 16252.311312256921, z: 9000 }, { x: -10010, y: 6682.102284251667, z: 9000 }, ]; function initMat() { let materialConfig = new Glodon.Bimface.Plugins.Material.MaterialConfig(); materialConfig.viewer = viewer; materialConfig.src = "/led.png"; return new Glodon.Bimface.Plugins.Material.Material(materialConfig); } wallEffectConfig.material = initMat(); const wallEffect = new Glodon.Bimface.Plugins.Animation.WallEffect(wallEffectConfig); } //设置默认UI隐藏 const setUIHide = (data) => { data.forEach(item => { let node = document.querySelector(item); if(node&&node.style){ node.style.display = "none"; } }) } //添加自定义按钮 const addCustomButton = (obj) => { if (!obj) return; var btnConfig = new Glodon.Bimface.UI.Button.ButtonConfig(); btnConfig.title = obj.title ? obj.title : ""; var btn = new Glodon.Bimface.UI.Button.Button(btnConfig); btn.setHtml(obj.iconHtml ? obj.iconHtml : ''); if (obj.defaultChecked) { btn.addClassName('bf-checked'); } if (obj.className) btn.addClassName(obj.className); btn.addEventListener('Click', function () { if ($(this).hasClass("bf-checked")) { $(this).removeClass("bf-checked"); if (obj.unchecked && typeof obj.unchecked == "function") obj.unchecked(); } else { $(this).addClass("bf-checked"); if (obj.checked && typeof obj.checked == "function") obj.checked(); } }); var toolbar = app.getToolbar('MainToolbar'); toolbar.insertControl(toolbar._controls.length, btn); } //给构建设置颜色 const setOverrideComponentsColorById = (ids, color) => { viewer.enableGlowEffect(true); viewer.overrideComponentsColorById(ids, color); viewer.render(); } // 销毁场景 const destroyViewer = () => { app && app.destroy(); } export { loadModel,//加载bim模型 destroyViewer,//销毁场景 floorExplosion, showFloor, showFloorBias, progressMonitor, showRooms, showRoomTemperature, showRoomPerson, showMeetingRoom, showRoomElecChart, showElecArea, showRoomWebsite, showSthFromVueComponent, showElevation, showCamera, emergency, showVideo, showLED, glowSelection, blinkSelection, anchorSelection, setUIHide,//隐藏bim默认UI addCustomItem,//添加自定义元素 deleteCustomItemById,//删除自定义元素通过id hideCustomItemById,//隐藏自定义元素通过id showCustomItemById,//显示自定义元素通过id addCustomButton,//添加自定义按钮 setTransparentComponentsById,//设置构建半透明状态通过构建id setOpaqueComponentsById,//取消构建半透明状态通过构建id onClick,//绑定bim构建点击回调 setOverrideComponentsColorById,//设置构建颜色 };