mirror of
https://gitee.com/iioter/iotgateway.git
synced 2024-11-29 18:28:09 +08:00
282 lines
6.8 KiB
HTML
282 lines
6.8 KiB
HTML
|
<!DOCTYPE html>
|
|||
|
<html lang="en">
|
|||
|
|
|||
|
<head>
|
|||
|
<title>3D</title>
|
|||
|
<meta charset="utf-8">
|
|||
|
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
|||
|
<link type="text/css" rel="stylesheet" href="./css/main.css">
|
|||
|
<style>
|
|||
|
body {
|
|||
|
background-color: #bfe3dd;
|
|||
|
color: #000;
|
|||
|
}
|
|||
|
|
|||
|
a {
|
|||
|
color: #2983ff;
|
|||
|
}
|
|||
|
</style>
|
|||
|
</head>
|
|||
|
|
|||
|
<body>
|
|||
|
|
|||
|
<div id="container"></div>
|
|||
|
<script src="../jquery.min.js"></script>
|
|||
|
<script src="../mqtt.min.js"></script>
|
|||
|
<script type="module">
|
|||
|
import * as THREE from './lib/three.module.js';
|
|||
|
|
|||
|
import Stats from './lib/stats.module.js';
|
|||
|
|
|||
|
import { OrbitControls } from './lib/OrbitControls.js';
|
|||
|
import { RoomEnvironment } from './lib/RoomEnvironment.js';
|
|||
|
|
|||
|
import { GLTFLoader } from './lib/GLTFLoader.js';
|
|||
|
import { DRACOLoader } from './lib/DRACOLoader.js';
|
|||
|
import { CSS3DObject, CSS3DRenderer } from './lib/CSS3DRenderer.js';
|
|||
|
|
|||
|
let W = window.innerWidth;
|
|||
|
let H = window.innerHeight;
|
|||
|
let mixer;
|
|||
|
let labelArr = [];
|
|||
|
|
|||
|
//标签数据
|
|||
|
let modelData = [{
|
|||
|
id: 1,
|
|||
|
cname: "Modbus设备",
|
|||
|
ename: "modbus_01",
|
|||
|
position: {
|
|||
|
x: -0.5,
|
|||
|
y: 0.6,
|
|||
|
z: 1.55,
|
|||
|
},
|
|||
|
param: [{
|
|||
|
name: "温度",
|
|||
|
value: 123,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "湿度",
|
|||
|
value: 123,
|
|||
|
},
|
|||
|
],
|
|||
|
}
|
|||
|
];
|
|||
|
|
|||
|
//定时更新数据
|
|||
|
//setInterval(() => {
|
|||
|
// modelData.forEach((item) => {
|
|||
|
// if (item.id > 0) {
|
|||
|
// item.param[0].value = parseInt(Math.random() * 30 + 150).toFixed(0);
|
|||
|
// item.param[1].value = parseInt(Math.random() * 30 + 150).toFixed(0);
|
|||
|
// }
|
|||
|
// });
|
|||
|
|
|||
|
// updateData();
|
|||
|
|
|||
|
//}, 2000);
|
|||
|
inimqttclient();
|
|||
|
const clock = new THREE.Clock();
|
|||
|
const container = document.getElementById('container');
|
|||
|
|
|||
|
const stats = new Stats();
|
|||
|
container.appendChild(stats.dom);
|
|||
|
|
|||
|
const css3dRenderer = new CSS3DRenderer();
|
|||
|
css3dRenderer.setSize(W, H);
|
|||
|
css3dRenderer.domElement.style.position = 'absolute';
|
|||
|
css3dRenderer.domElement.style.top = 0;
|
|||
|
container.appendChild(css3dRenderer.domElement);
|
|||
|
|
|||
|
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
|||
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|||
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|||
|
renderer.outputEncoding = THREE.sRGBEncoding;
|
|||
|
container.appendChild(renderer.domElement);
|
|||
|
|
|||
|
const pmremGenerator = new THREE.PMREMGenerator(renderer);
|
|||
|
|
|||
|
const scene = new THREE.Scene();
|
|||
|
scene.background = new THREE.Color(0xbfe3dd);
|
|||
|
scene.environment = pmremGenerator.fromScene(new RoomEnvironment(), 0.04).texture;
|
|||
|
|
|||
|
const camera = new THREE.PerspectiveCamera(40, W / H, .1, 10000);
|
|||
|
camera.position.set(5, 2, 8);
|
|||
|
|
|||
|
const controls = new OrbitControls(camera, container);
|
|||
|
controls.target.set(0, 0.5, 0);
|
|||
|
controls.update();
|
|||
|
controls.enablePan = false;
|
|||
|
controls.enableDamping = true;
|
|||
|
|
|||
|
const dracoLoader = new DRACOLoader();
|
|||
|
dracoLoader.setDecoderPath('./lib/gltf/');
|
|||
|
|
|||
|
const loader = new GLTFLoader();
|
|||
|
loader.setDRACOLoader(dracoLoader);
|
|||
|
loader.load('./model/LittlestTokyo.glb', function (gltf) {
|
|||
|
|
|||
|
const model = gltf.scene;
|
|||
|
model.position.set(1, 1, 0);
|
|||
|
model.scale.set(0.01, 0.01, 0.01);
|
|||
|
scene.add(model);
|
|||
|
|
|||
|
createLableArr();
|
|||
|
|
|||
|
mixer = new THREE.AnimationMixer(model);
|
|||
|
mixer.clipAction(gltf.animations[0]).play();
|
|||
|
|
|||
|
animate();
|
|||
|
|
|||
|
}, undefined, function (e) {
|
|||
|
|
|||
|
console.error(e);
|
|||
|
|
|||
|
});
|
|||
|
|
|||
|
//创建标签
|
|||
|
function createLableArr() {
|
|||
|
let style = "color: #00CED1;cursor:pointer;font-size:30px;padding:5px 15px;"; //background:#43bafe;
|
|||
|
modelData.forEach((item) => {
|
|||
|
let label = createLabel(item.cname, style, item.param);
|
|||
|
label.position.set(item.position.x, item.position.y, item.position.z);
|
|||
|
let scale = 0.003;
|
|||
|
label.scale.set(scale, scale, scale); //缩放比例
|
|||
|
label.name = item.ename;
|
|||
|
//label.visible = true;
|
|||
|
scene.add(label);
|
|||
|
labelArr.push(label);
|
|||
|
|
|||
|
const axesHelper = new THREE.AxesHelper(5);
|
|||
|
label.add(axesHelper);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/**销毁模型*/
|
|||
|
function destroyObject(object) {
|
|||
|
if (!object) return;
|
|||
|
object.traverse((item) => {
|
|||
|
if (item.material) {
|
|||
|
if (Array.isArray(item.material)) {
|
|||
|
item.material.forEach(m => m.dispose());
|
|||
|
} else {
|
|||
|
item.material.dispose();
|
|||
|
}
|
|||
|
}
|
|||
|
if (item.geometry) item.geometry.dispose();
|
|||
|
item = null;
|
|||
|
});
|
|||
|
|
|||
|
scene.remove(object);
|
|||
|
object = null;
|
|||
|
}
|
|||
|
|
|||
|
/**信息标注的生成*/
|
|||
|
function createLabel(text, style, param) {
|
|||
|
//创建CSS3D
|
|||
|
let div_label = document.createElement("div");
|
|||
|
div_label.className = "div-label";
|
|||
|
let div_ul = document.createElement("ul");
|
|||
|
let div_li = document.createElement("li");
|
|||
|
|
|||
|
style ? (div_li.style = style) : "";
|
|||
|
div_li.textContent = `设备名称:${text}`;
|
|||
|
div_ul.appendChild(div_li);
|
|||
|
|
|||
|
if (param.length) {
|
|||
|
param.forEach((item) => {
|
|||
|
let param_li = document.createElement("li");
|
|||
|
style ? (param_li.style = style) : "";
|
|||
|
param_li.textContent = `${item.name}:${item.value}`;
|
|||
|
div_ul.appendChild(param_li);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
div_label.appendChild(div_ul);
|
|||
|
let label = new CSS3DObject(div_label);
|
|||
|
|
|||
|
return label;
|
|||
|
}
|
|||
|
|
|||
|
//更新数据标签
|
|||
|
function updateData() {
|
|||
|
if (labelArr.length) {
|
|||
|
labelArr.forEach(item => {
|
|||
|
destroyObject(item);
|
|||
|
});
|
|||
|
createLableArr();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
window.onresize = function () {
|
|||
|
|
|||
|
camera.aspect = window.innerWidth / window.innerHeight;
|
|||
|
camera.updateProjectionMatrix();
|
|||
|
|
|||
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
function animate() {
|
|||
|
|
|||
|
requestAnimationFrame(animate);
|
|||
|
|
|||
|
const delta = clock.getDelta();
|
|||
|
|
|||
|
mixer.update(delta);
|
|||
|
|
|||
|
controls.update();
|
|||
|
|
|||
|
//标签
|
|||
|
// if (labelArr.length) {
|
|||
|
// labelArr.forEach((item) => {
|
|||
|
// if (item.visible) {
|
|||
|
// item.quaternion.slerp(camera.quaternion, 1);
|
|||
|
// }
|
|||
|
// });
|
|||
|
// }
|
|||
|
|
|||
|
stats.update();
|
|||
|
|
|||
|
renderer.render(scene, camera);
|
|||
|
css3dRenderer.render(scene, camera);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
function inimqttclient() {
|
|||
|
var options = {
|
|||
|
//mqtt客户端的id,这里面应该还可以加上其他参数,具体看官方文档
|
|||
|
clientId: 'mqttjs3d_' + (Math.random() * 10000000).toString()
|
|||
|
}
|
|||
|
var client = mqtt.connect('ws://' + window.location.host + '/mqtt', options);
|
|||
|
client.on('connect', function () {
|
|||
|
client.subscribe('internal/v1/gateway/telemetry/+/+', function (err) {
|
|||
|
if (!err) {
|
|||
|
console.log("订阅成功!")
|
|||
|
} else {
|
|||
|
console.log(err)
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
|
|||
|
client.on('message', function (topic, message) {
|
|||
|
if (topic == 'internal/v1/gateway/telemetry/Modbus/temperature') {
|
|||
|
var objmsg = $.parseJSON(message.toString());
|
|||
|
modelData[0].param[0].value = objmsg.CookedValue;
|
|||
|
updateData();
|
|||
|
} else if (topic == 'internal/v1/gateway/telemetry/Modbus/humidity') {
|
|||
|
var objmsg = $.parseJSON(message.toString());
|
|||
|
modelData[0].param[1].value = objmsg.CookedValue;
|
|||
|
updateData();
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
</body>
|
|||
|
|
|||
|
</html>
|