原标题:稳了,ThingJS平台让新手都能搭成数据中心3D机房
是否还在担心人手不够,工期太长,搞不定机房的3D可视化应用,别担心了,脚本都给你,代码都给你,一顿操作猛如虎,来试试吧!
数据中心3D机房三维可视化管理项目,是ThingJS提供给广大用户的开源项目,用户可以通过借鉴或者使用这个开源项目完成属于自己的第一个3D机房三维可视化管理应用,同时,也可以在该项目中增加所需功能,如Echarts图表+数据交互,或是查看ThingJS提供的官方示例进行相关修改。
总览:
机柜信息:
空间统计:
脚本:
document.title = 'Demo-机房管理';
/**
* 机房demo
* @author larrow 2018.05.01
*/
var app = new THING.App({
url: 'models/comproom/'
});
app.on('load', function() {
// 摄影机飞行到合适位置
app.camera.flyTo({
time: 1000,
position: [-15.8, 14.3, 17.9],
target: [0.3, -2.0, 1.5]
});
// 初始化机柜等物体
init_cabinets();
// 初始化界面
init_ui();
});
// ------------------------------------------------------------------------------
// 机柜相关
const CABINET_DEFAULT_UNITCOUNT = 42; // 默认机柜u数
const RACK_UNIT_HEIGHT = 0.0445; // 1u为4.3厘米
const BarGraphColors = ['#0000ff', '#00ffff', '#00ff00', '#ff0000', '#ff00ff', '#ffff00'];
/**
* Cabinet 机柜类
*/
class Cabinet extends THING.Thing {
constructor(app) {
super(app);
this.racks = [];
this.isCabinet = true;
this.barGraph = null;
this.ui = null;
this.number = Math.randomInt(100, 300);
}
createRack(url, u) {
var y = u * RACK_UNIT_HEIGHT;
var cabinet = this;
var rack = this.app.create({
type: 'Rack',
name: 'rack',
url: url,
complete: function() {
cabinet.add({
object: this,
basePoint: 'BasePoint',
localPosition: [0, y, 0],
localAngles: [0, 0, 0]
});
}
});
return rack;
}
createRacks() {
var curUPos = 0;
while(true) {
var pair = RackModels[Math.randomInt(0, RackModels.length - 1)];
var url = pair[0];
var uHeight = pair[1];
var rack = this.createRack(url, curUPos);
this.racks.push(rack);
if (curUPos >= CABINET_DEFAULT_UNITCOUNT - 4)
break;
curUPos += uHeight;
}
return rack;
}
destroyRacks() {
for (var i = 0; i < this.racks.length; i ++) {
var rack = this.racks[i];
rack.destroy();
}
this.racks = [];
}
openDoor() {
this.playAnimation('open1');
this.createRacks();
}
closeDoor() {
this.playAnimation({
name: 'close1',
complete: function() {
this.destroyRacks();
if (Rack.current)
Rack.current.showUI(false);
}
});
}
// 创建柱状图
createBarGraph() {
if (this.barGraph)
return;
var box = app.create({
type: 'Box',
width: this.size[0] * 0.9,
height: this.size[1],
depth: this.size[2] * 0.9,
position: this.position,
center: 'Bottom'
});
this.barGraph = box;
}
// 显示柱状图
showBarGraph(bool) {
if (bool) {
// 确认创建了盒子
this.createBarGraph();
// 隐藏机柜,显示盒子
this.visible = false;
this.barGraph.visible = true;
this.barGraph.style.color = Math.randomFromArray(BarGraphColors);
//this.barGraph.style.opacity = 0.9;
// 缩放盒子
this.barGraph.scale = [1, 0.1, 1];
this.barGraph.scaleTo({
scale: [1, Math.randomFloat(0.2, 1.0), 1],
time: 400,
lerpType: THING.LerpType.Linear.Quadratic
});
} else {
// 隐藏盒子,显示机柜
this.visible = true;
if (this.barGraph)
this.barGraph.visible = false;
}
}
// 创建界面
createUI() {
if (this.ui)
return;
var cabinet = this;
// 创建widget (动态绑定数据用)
var panel = new THING.widget.Panel({
width: "230px",
closeIcon: false,
opacity: 0.8,
});
this.panel = panel;
panel.addString(this, 'name').name('机柜'+this.number);
// 创建obj ui (跟随物体用)
var ui = app.create({
type: 'UI',
parent: this,
el: panel.domElement,
offset: [0, cabinet.size[1], 0]
});
this.ui = ui;
}
// 显示界面
showUI(boolValue) {
if (!this.ui)
this.createUI();
this.panel.visible = boolValue;
}
}
THING.factory.registerClass('Cabinet', Cabinet);
Cabinet.current = null;
Cabinet.open = false;
// 架式设备模型
const RackModels = [
['https://model.3dmomoda.cn/models/3817338017ff4776a5dd05f03a3e2fd4/0/gltf', 1],
['https://model.3dmomoda.cn/models/37972dd2c96c4a37a3245a00bee3628b/0/gltf', 2]
];
/**
* Rack 架式设备
*/
class Rack extends THING.Thing {
constructor(app) {
super(app);
this.isRack = true;
this.info = gen_rack_info();
}
createUI() {
var ui = new THING.widget.Panel({
titleText: this.name,
closeIcon: true,
dragable: true,
retractable: true,
hasTitle: true,
width: "228px",
});
ui.zIndex = 999999;//设置ui排序
ui.addTab(this.info);
ui.position = [390, 350];
this.ui = ui;
return ui;
}
showUI(boolValue) {
if (!this.ui)
this.createUI();
this.ui.show(boolValue);
}
}
THING.factory.registerClass('Rack', Rack);
Rack.current = null;
function gen_rack_info() {
var type2 = ["PC服务器", "路由器"];
var type3 = ["IBM", "HP", "DELL"];
var people = ["王WW", "李LL", "张ZZ"];
var info = {
"基本信息": {
"一级分类": "微机",
"二级分类": type2[Math.randomInt(0,1)],
"设备类型": type3[Math.randomInt(0,2)],
"编号": "00" + Math.randomInt(0, 9),
"使用人": people[Math.randomInt(0,2)],
"管理员": people[Math.randomInt(0,2)],
"上架时间": ""+Math.randomInt(10,23)+":"+Math.randomInt(10,23),
},
"扩展信息": {
"信息XX": Math.ceil(Math.random() * 27 + 25) + "",
"信息YY": Math.ceil(Math.random() * 25 + 20) + "",
"信息ZZ": Math.ceil(Math.random() * 27 + 25) + "",
"信息AA": Math.ceil(Math.random() * 25 + 20) + "",
"信息BB": Math.ceil(Math.random() * 27 + 25) + "",
"信息CC": Math.ceil(Math.random() * 25 + 20) + "",
"信息DD": Math.ceil(Math.random() * 25 + 20) + "",
}
};
return info;
}
// 初始化机柜
function init_cabinets() {
var cabinets = app.query('.Cabinet');
// 双击左键开门
cabinets.on('dblclick', function() {
// 摄影机飞行
var pos = this.selfToWorld([0, 2.0, 2.1]);
//var pos = this.selfToWorld([-0.6, 1.1, 2.3]);
var targ = this.position;
targ[1] += 0.95;
app.camera.flyTo({
time: 1000,
position: pos,
target: targ,
});
// 机柜开门动画
if (Cabinet.current) {
Cabinet.current.closeDoor();
Cabinet.current = null;
}
this.openDoor();
// 设置为当前
Cabinet.current = this;
this.style.outlineColor = null; // 当前机柜不沟边
})
// 右键关门
app.on('click', function(event) {
if (event.button == 2) {
if (Cabinet.current) {
Cabinet.current.closeDoor();
Cabinet.current = null;
} else {
// 如果没有当前机柜则飞到一个最佳位置
app.camera.flyTo({
time: 1500,
position: [-10.4, 13.6, 12.3],
target: [3.6, -4, -1.7],
});
}
}
});
// 机柜 滑过沟边
cabinets.on('mouseon', function () {
if (this != Cabinet.current) {
this.style.outlineColor = '#00ff00';
this.showUI(true);
}
});
cabinets.on('mouseoff', function () {
this.style.outlineColor = null;
this.showUI(false);
});
// 架式服务器事件(尚未创建,预先注册)
app.on('mouseon', '.Rack', null, function (ev) {
this.style.outlineColor = '#ff0000';
});
app.on('mouseoff', '.Rack', null, function (ev) {
this.style.outlineColor = null;
});
app.on('click', '.Rack', null, function (ev) {
if (Rack.current == this)
return;
if (Rack.current) {
Rack.current.showUI(false);
Rack.current = null;
}
Rack.current = this;
this.showUI(true);
});
}
// ------------------------------------------------------------------------------
// 一个工具面板
function init_ui() {
new THING.widget.Button('开场动画', function() {
openingShow.start();
app.query('.Cabinet').forEach(function(obj) {
obj.showBarGraph(false);
});
});
var showBar = true;
new THING.widget.Button('空间统计', function() {
openingShow.stop();
app.query('.Cabinet').forEach(function(obj) {
obj.showBarGraph(showBar);
});
showBar = !showBar;
});
}
// ------------------------------------------------------------------------------
// 开场秀
openingShow = {
curShowIdx: 0, // 当前进行的是哪一场show
objCount: 0, // 计算有多少物体已经完成了表演
showing: false,
showInfo: null,
inited: false,
init: function() {
var that = this;
// 每次show的对象 查询字符串、时间、摄影机位置
this.showInfo = [
[ "[Group=Inside01]", 500, [-7.1, 8.8, 9.2], [-3.1, 3, 0.2] ],
[ "[Group=Inside02]", 500, [-9.5, 8.6, 11.7], [-3.5, 3, 5.3] ],
[ "[Group=Inside03]", 500, [13.9, 9.3, 15.1], [8.9, 3, 5.8] ],
[ "[Group=Inside04]", 500, [19.9, 10.3, 7.9], [16.5, 3, 3.9] ],
[ "[Group=Inside05]", 500, [27.3, 11.5, 11.8], [23.3, 3, 4.4] ],
[ "[Group=Outside01] | [Group=Outside03]", 300, [10.3, 45.7, 28], [9.7, 3.1, 4.5] ],
[ "[Group=Outside02] | [Group=Outside04]", 300, [-10.3, 21.2, 32.7], [6.6, 3, 0.7] ],
];
// 注册取消事件
app.on('keydown', function(event) {
if (event.key == "Escape") {
that.stop();
}
})
this.inited = true;
},
// 开始show
start: function() {
if (this.showing)
return;
if (!this.inited)
this.init();
this.showing = true;
// 所有具有属性Group值包含Inside的都抬高
app.query("[Group=Inside*]").forEach(function(obj) {
obj.visible = false;
obj.initPos = obj.position; // 保存一下初始位置
obj.translate([0, 10, 0]);
});
// 所有具有属性Group值包含Outside的都偏移z
app.query("[Group=Outside*]").forEach(function(obj) {
obj.visible = false;
obj.initPos = obj.position; // 保存一下初始位置
obj.translate([0, 0, 10]);
});
this.step();
},
// 每一个show的过程
step: function() {
var info = this.showInfo[this.curShowIdx];
var queryString = info[0];
var costTime = info[1];
var camPos = info[2];
var camTarget = info[3];
var nextNow = info[4];
// 摄影机飞行
var that = this;
app.camera.flyTo({
time: 800,
position: camPos,
target: camTarget,
complete: function() {
// 机柜等设备飞入效果
var dealyTime = 0;
var objIdx = 0;
app.query(queryString).forEach(function(obj) {
that.objCount ++;
obj.visible = true;
obj.moveTo({
position: obj.initPos,
time: costTime,
delayTime: dealyTime,
lerp: true,
lerpType: THING.LerpType.Cubic.In,
complete: function() {
that.next();
}
});
// 逐步提高速度
dealyTime = (objIdx > 16) ? (dealyTime + 30) : (dealyTime + 100); // 延时加速
objIdx ++;
});
}
});
},
// 下一次show的判断
next: function() {
if (!this.showing)
return;
// 本场show演员还没全部完成
this.objCount --;
if (this.objCount > 0)
return;
// 全部结束
this.curShowIdx ++;
if (this.curShowIdx >= this.showInfo.length) {
this.showing = false;
this.curShowIdx = 0;
console.log('all show finish!');
return;
}
// 下一show
this.step();
},
stop: function() {
app.query("[Group]").forEach(function(obj) {
obj.stopMoving();
obj.visible = true;
obj.position = obj.initPos
});
app.camera.stopFlying();
this.objCount = 0;
this.curShowIdx = 0;
this.showing = false;
}
}
本文由优锘ThingJS面向物联网的3D可视化开发平台整理发布http://www.thingjs.com/ 欢迎加入开发大群225986500游戏网
责任编辑:
相关下载 |
以上就是小编给大家带来的《TheShy终于拿出锐雯!残血反杀秀操作》内容了,更多好看好玩的游戏资讯,请关注234游戏网,感谢您的支持。 详情>>
本篇中小编将为您讲解了标题为《Theshy蛇女1人包围对手,简直是魔鬼》的内容详解。之前本站也有不少类似内容介绍,详情可以点击234游戏网中查看,感谢您对我们的支持。详情>>
TheShy职业生涯Top5,1人抓单5个,惊艳全球解说详情>>
theshy遇见了爱情?网友表示般配详情>>
昨晚SKT被G2斩落马下,目睹了3-0的琪亚娜一步步变成4-5,看着记忆中一向稳如泰山的大魔王慌张颤抖的左手,许多观众都在摇头叹息,原来神也终究会老,也许自己的青春就要详情>>
S9全球总决赛小组赛最终比赛日,iG战队赛前宣布Ning回归首发,完全体iG首次在S9世界赛亮相。 最终在iG众人的努力下,iG成功突围晋级八强赛,赛后TheShy与Ning握手一幕引详情>>
英雄联盟S9世界赛迎来了IG对阵TL的比赛。IG是LPL赛区的三号种子,TL战队是北美赛区的头号种子。而且,IG同TL在世界级别的赛事中都是处于劣势之中的,尤其是最近的MSI季中详情>>
S9世界赛即将打响,韩媒采访了退役世界冠军打野选手Ambition,与他一起谈论关于本次世界小组赛的内容 图源:Riot Games Q.世界赛入围赛结束了,看完你的感想是? 这是LC详情>>
原标题:Theshy欧服放出烟雾弹,英雄池再添杀招,苦练法师隐藏战术 大家好,英雄联盟IG战队的上单选手Theshy,他在最近一段时间打欧服的Rank对局,让不少LPL详情>>
原标题:LOL:Rookie撞车TheShy被恰分,愤怒要求solo,单杀制裁! 英雄联盟S9世界赛前夕,Rookie和TheShy在一场排位中又撞车了!TheShy的剑魔对上Rookie的阿卡丽,R详情>>
原标题:荷兰宣布国名拼写恢复使用“the Netherlands” 欧联网10月10日电 据欧联通讯社报道,荷兰政府日前宣布,今后国名拼写将不再使用“Holland”,一详情>>
原标题:拳头解说评S9选手TOP20引争议,Faker第一,TheShy排名倒数? 拳头官方的两位解说Jazz和Vedius评选出了他们心中的选手TOP20,据悉这份榜单是按照持续详情>>
原标题:解说评S9选手TOP20:李哥成公认第一 TheShy排名却引争议 拳头官方解说JATT与VEDIUS评选出了他们心中的世界赛选手TOP20,需要注明的是,这并不是官详情>>
原标题:见过一字眉、柳叶眉、高挑眉,但你有见过麦当劳眉吗? 今日问题 ⊙“麦当劳眉毛”怎么说?⊙ These days, there are about a thousand different详情>>
原标题:iG公布首发名单 小乐言代替宁王登场 英雄联盟S9小组赛前夕,官方公布了第一个比赛日战队首发名单,其中iG真如大家想象的那样启用了小乐言为首详情>>
原标题:iG小组赛阵容公布,TheShy乐言首发 粉丝狂喜:这阵容出线稳了! 自从iG公布S9出征名单之后,玩家们就十分关注小组赛的首发阵容是什么。一直有传宁王详情>>
原标题:宁王和theshy合体练潘森,宁王11杀0死带羞男胜利,宁王回来了? 自从Theshy选手跟替补打野小乐言合体双排之后,大多数观众都认为宁王基本上已经被IG详情>>
原标题:MLXG排位偶遇theshy,再现世界第一剑姬,香锅:我躺的好舒服 英雄联盟s9总决赛马上就要迎来lpl的赛事,目前锅老师在欧服创建了新号,开始欧详情>>
原标题:LPL要凉?Theshy胜率居然倒数第五,狼行胜率反向登顶太真实 不知不觉间,英雄联盟S9世界赛已经开赛一周了,在看完休闲下饭的入围赛之后,小组赛的日子详情>>
原标题:FPX金贡采访直言:最不想遇到TheShy,他是压我100刀的男人! 英雄联盟S9小组赛即将开始,作为LPL头号种子,同时也是第一次参加世界赛的队伍。FPX全队上详情>>
原标题:Theshy在柏林狂练剑姬,MLXG化身舔狗:哥,算了,别上 英雄联盟小组赛(正赛)即将举行,我们LPL赛区的三支队伍 IG、FPX以及RNG也将逐一亮相。目前这三支队详情>>
原标题:当mlxg遇上Theshy:5分钟来上路三次,香锅:IG打野有这么难么? 在S9总决赛的这段时间中,欧服突然就成为了各大赛区粉丝们的焦点——毕竟现在所有参详情>>
最近各大赛区选手云集LEC赛区,高强度的rank来适应比赛的9.19版本,可谓是苦了欧服玩家。其中LPL三支战队也相继到达欧服开始了上分之旅,其中以IG战队的the shy表现最为强劲详情>>
原标题:当mlxg遇上Theshy:5分钟来上路三次,香锅:IG打野有这么难么? 在S9总决赛的这段时间中,欧服突然就成为了各大赛区粉丝们的焦点——毕竟现在所有参加S详情>>
原标题:ThinkPad X1 Carbon LTE版本上架:6核i7/16GB内存,13999元起 IT之家10月9日消息 ThinkPad X1 Carbon今年再度更新,不仅全系加入了LTE联网,更是标详情>>
原标题:Mlxg欧服排到TheShy,全程上路当“狗”!Ning因此再度躺枪 MLXG最近一直在玩欧服,S9小组赛临近,参赛队员们平日训练也都在欧服扎堆,因此就经常出现和详情>>
原标题:ThinkPad E14笔记本上架:i5-10210U/RX 640,首发价5499元 IT之家10月9日消息 近日,联想ThinkPad 悄然推出了E14笔记本,搭载了英特尔最新的10代酷详情>>
S9全球总决赛小组赛还有不到一周的时间就要开赛了,各大战队的粉丝也是高强度的盯着OB直播间,来确定队员的状态和手感。 目前来看队员们似乎都还不错,之前一直被诟病的R详情>>
原标题:S9两大“死亡之组”出炉,Nuguri如愿遇到Theshy,狼行压力山大! 10月9日,《英雄联盟》S9入围赛阶段的比赛正式落下帷幕,HKA 3-1击败ISG战队,SPY 3-2带详情>>
原标题:Uzi排位偶遇TheShy,却无意暴露RNG大招,打赢SKT就看这一手了? 大家好,我是A电竞精分双子十二羊。全球总决赛已经开始了,如今已经进行到入围赛的最后详情>>
原标题:CG孙哥坦言RNG下路组合是S9最强!DWG上单渴望进D组被TheShy教育 10月7号晚上S9入围赛淘汰赛拉开帷幕,第一轮比赛角逐出两支队伍晋级,DWG 3:1 LK详情>>
S9世界赛,由于今年LPL三支种子队直接保送正赛,所以入围赛阶段的比赛也少了很多看点。不过LPL三队都已经抵达了欧洲赛场,并且开启了紧张的赛前训练状态。今年S9世界赛采详情>>
原标题:TheShy被Uzi越级单杀,落后100刀细节无敌!网友:狼行你走吧 S9小组赛即将开赛,目前LPL几支参赛队伍都已经前往欧洲备战,职业选手们自然也入乡随俗玩详情>>
原标题:欧服玩家排位抢走刀妹,想单杀对手Theshy,对拼结果太扎心 大家好,喜欢IG战队的上单选手Theshy的英雄联盟玩家,都十分清楚Theshy这位英雄联盟职业详情>>
原标题:电竞晨报:LK院长级小炮偷家DWG 小狗实力单杀TheShy 大家早上好,欢迎收看兔玩电竞晨报,之后的每天都会给大家带来电竞圈最新鲜的八卦资讯,一起来看详情>>
LPL的三支战队在抵达欧洲之后,所有选手的ID基本都已经确定,现在IG战队的选手RANK分数最高状态似乎要更好一些,其中TheShy的个人战绩也是引发了观众的热议,这个选手在排位中详情>>