金融业务可视化管理如何实现?
一说到银行业务保密性就会加强,所以以往我们的银行案例就不在这里给大家具体介绍,今天只讲金融业务可视化管理如何实现?对网点、金库、ATM等银行设备设施及运维、现金库存、金库调缴等业务进行可视化,在立体视角下掌控全局,为银行设备运维、现金服务及客户服务的状态监控提供三维可视化管理工具。脑补即可~运维场景可在thingjs平台查看哦~
基本概念
对象的定义
ThingJS 平台的对象是指一个使用 ThingJS 提供的各种类创建的物体实例,不同类的对象实例具有不同接口和功能,比如我们在场景里创建一个园区,园区就是一个对象,园区里的建筑和物体都是对象。
模型的定义
ThingJS 平台的模型是指可复用的 3D 资源包,有些对象实例创建时指定模型资源的路径。
ThingJS 提供了具有丰富资源的模型库(ThingDepot)。
场景的定义
启动 ThingJS 后,ThingJS 就会创建一个三维空间,整个三维空间我们称之为“场景”(scene),在场景内我们可以创建对象,比如园区,楼宇,车辆,传感器等等。
园区的定义
通过 CamBuilder 可编辑并输出一个园区,该园区可在 ThingJS 场景中加载。
项目的定义
ThingJS 平台的项目是指一个场景加上一个交互脚本。脚本使用 JavaScript 语言开发。例如 Demo 里的粮仓管理,交互功能包括点击仓库可以显示信息牌,点击屋顶可以开盖。
坐标系
坐标系概念
以场景原点为中心的直角坐标系称为世界坐标。
在 ThingJS 中所有的物体的 position 值均为世界坐标,排列为 [x,y,z] 。
世界坐标系
当在场景中创建了园区,在园区下我们放置一个模型,模型是园区的子物体,我们想在园区的坐标系下,设置模型的位置,这时使用的园区的坐标系,就是模型的父物体坐标系。
父物体坐标系
启动 ThingJS 后,ThingJS 就会创建一个三维空间,整个三维空间我们称之为“场景”(scene),在场景内我们可以创建对象,比如园区,楼宇,车辆,传感器等等。
自身坐标系
某对象向前移动 2 米,就是在自身坐标系下设置坐标 [0,0,2](Z轴正向朝向我们的方向)。
配置和部署
系统运行硬件的要求
ThingJS 的 3D 可视化应用是 B/S 架构的,3D 场景是运行在客户端的浏览器中。3D 场景渲染展示对客户端设备要求较高,特别是显卡,一般必须是独立显卡
推荐使用 Chrome 浏览器进行开发和演示。
客户端:
系统:Windows 7 及以上
CPU:双核 CPU2.8GHz及以上
内存:8G 及以上
显卡:最低 GTX650,推荐 GTX960 及以上,显存 2G 及以上
硬盘:300GB 及以上
ThingJS 若是离线部署,需要部署到服务器端,ThingJS 对服务器端的要求并不高
服务器端:
系统:Windows Server 2003 及以上
CPU:双核 CPU2.8GHz 及以上
内存:8G 及以上
硬盘:500GB及以上
软件环境:JDK 1.6 及以上
部署方式
支持项目 托管部署 和 离线部包部署 两种方式。
收费方式
开发者收费方式
个人开发者免费,适用于验证 3D 开发流程,制作 Demo 项目。
商业开发者按年收费,商业开发者适用于开发/测试物联网 3D 项目。
项目收费方式
ThingJS 平台按项目数量计费。
托管项目按一个项目一年授权的方式收费。
离线部署包按项目收费。
具体详情可点击 此处 进行了解查看。
项目托管
开发者使用项目托管,通过在线开发调试代码,在测试完成后,可一键发布,并且在有效期内可随时更新。
离线部署包
开发者在开发完成后可申请离线部署包一个月试用。试用期内可随时更新场景和代码。 测试完成后,购买永久授权码。使用永久授权码最终交付项目。而且永久授权脚本可以随时更新,更新后不需要新授权码。但是永久授权更新场景需提交审核,变动不超过 50%,1工作日内发放新授权码。
数据对接
对接的数据不用经过 ThingJS 平台,可以通过 Ajax 请求或者 WebSocket 方式获取服务器端的数据。
网速问题
在开发过程中出现加载慢等问题时,用户可先自行检测自己的网络是否正常,我们将会提供测试页面供用户检测。如果用户在正常时间范围内未打开测试页面,那么可能是由于用户网络的问题。
场景过大
每个用户搭建的场景不同,场景内的的物体数量也不确定,当场景内物体过多时也有可能会导致场景加载缓慢,卡顿。建议采用分批次加载,分室内外加载,动态加载等方式。
运行卡
场景内物体数量过多、开启了屏幕后期特效、请求后台数据频繁都可能造成性能损耗;代码脚本出现逻辑问题、客户端机器配置低等情况也会造成场景运行卡顿。
代码逻辑问题可通过log或者debuger进行检查。
document.title = 'Demo-建筑监控';
// 创建App
var app = new THING.App({
el: 'div3d',
url: "models/uinnova",
skyBox: 'BlueSky'
});
// 加载场景后执行
var building = null, mainPanel;
app.on('load', function () {
building = app.buildings[0];
mainPanle = new MainPanel(app);// 界面的类
setupNavpanel();
app.level.change(app.root.campuses[0]);
});
// 注册 进入室外 事件
app.on('afterEnterOutdoorsLevel', function (ev) {
building.facades[0].visible = true; // 显示外立面
var pos = building.position;
app.camera.flyTo({
position: [pos[0] + 3, pos[1] + 43.21, pos[2] + 80],
target: pos,
time: 1200
});
});
// 注册 进入建筑 事件
app.on('afterEnterBuildingLevel', function (ev) {
building.facades[0].visible = false; // 隐藏外立面
});
// 注册 进入楼层 事件
app.on('afterEnterFloorLevel', function (ev) {
building.facades[0].visible = false; // 隐藏外立面
var num = ev.state.floor.indexOfBuilding;
var pos = building.position;
app.camera.flyTo({
position: [pos[0] - 3, pos[1] + 20.28 + (num - 1) * 2.5, pos[2] + 56],
target: [pos[0], pos[1] + (num - 1) * 6, pos[2] + 15.76],
time: 1200
});
});
function initCSS(url) {
var link = document.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", url);
var heads = document.getElementsByTagName("head");
if (heads.length)
heads[0].appendChild(link);
else
document.documentElement.appendChild(link);
}
// 给导航面板添加点击事件
function setupNavpanel() {
var navPanel = mainPanle.createNavPanel();
navPanel.on('click', function (obj, target) { // 绑定 导航树 事件
navPanel.highLight(target);
if (obj == '全景') {
app.level.change(app.root.campuses[0]);
} else {
if (obj.name.indexOf('层') > -1) {
var num = obj.name.substring(0, 1);
var floor = building.floors[num];
// navPanel.pathHighLight('全景.建筑.' + num + '层');
app.level.change(floor);
} else {
// navPanel.pathHighLight('全景.' + obj.name);
app.level.change(app.root.campuses[0]);
}
}
})
}
class MainPanel {
constructor(app) {
this.app = app;
this.nav_tree = { // 导航树对象
buildings: [{ name: "建筑", floors: [{ name: "1层", }, { name: "2层", }, { name: "3层", }, { name: "4层", }, { name: "5层", }] }],
outdoor: { name: '室外' }
}
this.panels_xfs = [];
this.panels_xfsx = [];
this.panels_pyfj = [];
this.toolBar = null;
this.toolImgs = {};
this.isExpandBuilding = false;
this.createUIOnObjs(); // 创建 gui 面板
this.createToolsPanel();
this.building = this.app.buildings[0];
}
// 创建导航面板
createNavPanel() {
var main_panel = new THING.widget.NavPanel();
main_panel.setPosition(0, null, null, 0); // 设置面板 位置 (left/bottom/right/top)
main_panel.addAppTree('全景', this.nav_tree); // 创建导航树
return main_panel;
}
// 创建工具面板
createToolsPanel() {
var that = this;
var baseURL = "https://www.thingjs.com/static/images/uBuilding/";
this.toolBar = THING.widget.ToolBar({ width:'164px',media: true });
this.toolBar.data = { xfsx: false, pyfj: false, xfs: false, enterBuilding: false, expandBuilding: false };
this.toolBar.setPosition({ right: 0, top: 60 });
this.toolImgs.img0 = this.toolBar.addImageBoolean(this.toolBar.data, 'xfsx').name('消防水箱').imgUrl(baseURL + 'xfsx.png');
this.toolImgs.img1 = this.toolBar.addImageBoolean(this.toolBar.data, 'pyfj').name('排烟风机').imgUrl(baseURL + 'pyfj.png');
this.toolImgs.img2 = this.toolBar.addImageBoolean(this.toolBar.data, 'xfs').name('消防栓').imgUrl(baseURL + 'xfs.png');
this.toolImgs.img3 = this.toolBar.addImageBoolean(this.toolBar.data, 'enterBuilding').name('进入建筑').imgUrl(baseURL + 'jz.png');
this.toolImgs.img4 = this.toolBar.addImageBoolean(this.toolBar.data, 'expandBuilding').name('楼层展开').imgUrl(baseURL + 'zk.png');
this.toolImgs.img0.on('change', function (boolValue) { that.onChangeImageButton('xfsx', boolValue); });
this.toolImgs.img1.on('change', function (boolValue) { that.onChangeImageButton('pyfj', boolValue); });
this.toolImgs.img2.on('change', function (boolValue) { that.onChangeImageButton('xfs', boolValue); });
this.toolImgs.img3.on('change', function (boolValue) { that.onChangeImageButton('enterBuilding', boolValue); });
this.toolImgs.img4.on('change', function (boolValue) { that.onChangeImageButton('expandBuilding', boolValue); });
}
// 处理工具条按钮
onChangeImageButton(key, boolValue) {
var that = this;
if (key == "enterBuilding") { // 进入建筑/室外
this.resetExpand();
var name = boolValue ? '返回室外' : '进入建筑';
this.toolImgs.img3.name(name);
if (boolValue)
this.app.level.change(app.buildings[0]);
else
this.app.level.change(app.root.campuses[0]);
} else if (key == "expandBuilding") { // 楼层横向展开
this.app.level.change(app.buildings[0]); // 进入建筑
if (boolValue) {
this.building.expandFloors({
'time': 1000,
'length': 10,
'horzMode': false,
'hideRoof': true,
'complete': function () { that.isExpandBuilding = true; }
})
} else {
this.building.unexpandFloors({
'time': 500,
'complete': function () { that.isExpandBuilding = false; }
})
}
} else {
this.resetExpand();
this.app.level.change(app.root.campuses[0]);// 进入室外
if (key == "xfsx") { // 消防水箱
this.panels_xfsx.forEach(function (panel) { panel.show(boolValue); });
} else if (key == "pyfj") { // 排烟风机
this.panels_pyfj.forEach(function (panel) { panel.show(boolValue); });
} else if (key == "xfs") { // 消防栓
this.panels_xfs.forEach(function (panel) { panel.show(boolValue); });
}
}
}
// 展开的楼层收回去
resetExpand() {
var that = this;
if (this.isExpandBuilding) {
this.toolBar.data.expandBuilding = false;
this.building.unexpandFloors({
'time': 500,
'complete': function () { that.isExpandBuilding = false; }
})
}
}
// 根据不同类型创建样式
createPanels(type) {
var obj = {};
var that = this;
var gui = new THING.widget.Panel({ width: '120px', name: type, opacity: 0.8, cornerType: 's2c5', width: '150px', hasTitle: true});
gui.remember(obj);
gui.show(false);
switch (type) {
case "消防栓":
obj = { hydraulicPressure: '0.14MPa' };
gui.add(obj, 'hydraulicPressure').name('水压');
that.panels_xfs.push(gui);
break;
case "消防水箱":
obj = { waterlevel: '2.5米' };
gui.add(obj, 'waterlevel').name('水位');
that.panels_xfsx.push(gui);
break;
case "排烟风机":
obj = { state: '开' };
gui.add(obj, 'state').name('状态');
that.panels_pyfj.push(gui);
break;
}
return gui;
}
// 为3d物体添加面板
createUIOnObj(objs) {
var that = this;
objs.forEach(function (obj) {
that.app.create({
type: 'UI',
parent: obj,
el: that.createPanels(obj.custom['物体类型']).domElement,
offset: [0, 1, 0],
pivot: [0.5, 1]
})
})
}
// 收集需要加面板的 obj 并为其添加面板
createUIOnObjs() {
this.createUIOnObj(app.query('[物体类型=消防栓]'));
this.createUIOnObj(app.query('[物体类型=消防水箱]'));
this.createUIOnObj(app.query('[物体类型=排烟风机]'));
}
}