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 = `
|
<p style="margin: 10px">监控编号:Camera_${index}</p>
|
<img src="/camera.gif" />
|
`;
|
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) => {
|
console.log(color,1082)
|
let colorObj = new Glodon.Web.Graphics.Color(color.red?color.red:0, color.green?color.green:0, color.blue?color.blue:0, color.alpha?color.alpha:0.5)
|
viewer.enableGlowEffect(true);
|
viewer.overrideComponentsColorById(ids, colorObj);
|
viewer.render();
|
}
|
|
|
//设置水流效果
|
const setFlowEffect = (callback)=>{
|
if(typeof callback =='function')callback(Glodon,viewer)
|
}
|
|
|
|
|
|
// 销毁场景
|
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,//设置构建颜色
|
setFlowEffect,//设置水流效果
|
};
|