黄陂项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

529 lines
17 KiB

2 weeks ago
2 weeks ago
2 weeks ago
2 days ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 days ago
2 weeks ago
2 weeks ago
2 weeks ago
2 days ago
2 weeks ago
2 days ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
  1. // 从这里开始
  2. var h1 = null
  3. var h2 = null
  4. var h3 = null
  5. var oldtransformNodex = null
  6. var oldMeshOther = null
  7. var drag = null
  8. var isRotating = true // 控制整体旋转状态:true=自动旋转,false=停止
  9. var clickParentRotate = false // 仅标记「手动暂停」状态,不干扰鼠标划出逻辑
  10. // 新增:标记鼠标是否悬停在模型上(核心控制旋转恢复的开关)
  11. var isPointerOverModel = false
  12. var targetAngles = {
  13. default: { // 初始视角
  14. alpha: 2.5809,
  15. beta: 0.9804,
  16. radius: 3
  17. },
  18. alarm: { // 报警视角(示例)
  19. alpha: 3.1213,
  20. beta: 0.5855,
  21. radius: 3
  22. }
  23. }
  24. var camera
  25. BABYLON.DefaultLoadingScreen.prototype.displayLoadingUI = function() {
  26. if (document.getElementById('customLoadingScreenDiv')) {
  27. document.getElementById('customLoadingScreenDiv').style.display = 'initial'
  28. return
  29. }
  30. this._loadingDiv = document.createElement('div')
  31. this._loadingDiv.id = 'customLoadingScreenDiv'
  32. thecss = 'lohingifpc'
  33. thecss2 = 'zcpc'
  34. this._loadingDiv.innerHTML = "<div class='oka'><div class='" + thecss + "'><image src='./logok.gif' class='jiazaiimg'/></div></div>"
  35. this._resizeLoadingUI()
  36. window.addEventListener('resize', this._resizeLoadingUI)
  37. document.body.appendChild(this._loadingDiv)
  38. }
  39. // 重构通用的模型交互绑定函数(核心优化鼠标划入/划出逻辑)
  40. function bindModelPointerEvents(transformNodex, clickCallback, highlightColor) {
  41. var mesheses = null
  42. if (transformNodex.getClassName() === 'TransformNode') {
  43. mesheses = transformNodex.getChildMeshes(false)
  44. } else {
  45. mesheses = [transformNodex]
  46. }
  47. for (var i = 0; i < mesheses.length; i++) {
  48. const mesh = mesheses[i]
  49. mesh.actionManager = new BABYLON.ActionManager(scene)
  50. // 鼠标划入:停止旋转(无论之前是否在旋转)
  51. mesh.actionManager.registerAction(
  52. new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOverTrigger, function() {
  53. isPointerOverModel = true
  54. isRotating = false // 标记为停止状态
  55. camera.useAutoRotationBehavior = false // 立即停止旋转
  56. // 高亮逻辑(如果需要)
  57. if (highlightColor && h2) {
  58. h2.addMesh(mesh, highlightColor)
  59. }
  60. })
  61. )
  62. // 鼠标划出:无条件恢复旋转(核心修改!只要移出,就恢复,除非手动暂停)
  63. mesh.actionManager.registerAction(
  64. new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOutTrigger, function() {
  65. isPointerOverModel = false
  66. // 关键:只要不是「手动暂停」,就恢复旋转(没有其他额外条件)
  67. if (!clickParentRotate) {
  68. isRotating = true
  69. camera.useAutoRotationBehavior = true // 立即恢复旋转
  70. }
  71. // 移除高亮(如果需要)
  72. if (highlightColor && h2) {
  73. h2.removeMesh(mesh)
  74. }
  75. })
  76. )
  77. // 点击事件(不影响旋转逻辑)
  78. mesh.actionManager.registerAction(
  79. new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger, function() {
  80. try {
  81. clickCallback && clickCallback(transformNodex)
  82. } catch (error) {
  83. console.warn('点击回调执行失败:', error)
  84. }
  85. })
  86. )
  87. }
  88. }
  89. // 原prepareGroupButton2改为调用通用函数
  90. function prepareGroupButton2(transformNodex, color, qu) {
  91. bindModelPointerEvents(transformNodex, cameraClick, color || new BABYLON.Color3(0, 0, 1))
  92. }
  93. // 原prepareGroupButton3改为调用通用函数
  94. function prepareGroupButton3(transformNodex, color, qu) {
  95. bindModelPointerEvents(transformNodex, archCabinetsClick, color || new BABYLON.Color3(0, 1, 0))
  96. }
  97. BABYLON.DefaultLoadingScreen.prototype.hideLoadingUI = function() {
  98. show = 50
  99. document.getElementById('customLoadingScreenDiv').style.display = 'none'
  100. document.getElementById('customLoadingScreenDiv_first').style.display = 'none'
  101. document.title = '档案室'
  102. var prepareGroupButton2ByMesh = function(transformNodex, color, qu) {
  103. var mesheses = null
  104. if (transformNodex.getClassName() === 'Mesh') {
  105. mesheses = [transformNodex]
  106. }
  107. for (var i = 0; i < mesheses.length; i++) {
  108. const mesh = mesheses[i]
  109. mesh.actionManager = new BABYLON.ActionManager(scene)
  110. mesh.actionManager.registerAction(
  111. new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOverTrigger, function() {
  112. isPointerOverModel = true
  113. isRotating = false
  114. camera.useAutoRotationBehavior = false
  115. if (oldMeshOther != null) {
  116. oldMeshOther.removeBehavior(drag)
  117. var mesheses2 = oldMeshOther.getClassName() === 'Mesh' ? [oldMeshOther] : []
  118. mesheses2.forEach(m => {
  119. try { h2.removeMesh(m) } catch (e) {}
  120. })
  121. }
  122. oldMeshOther = transformNodex
  123. var mesheses3 = transformNodex.getClassName() === 'Mesh' ? [transformNodex] : []
  124. mesheses3.forEach(m => {
  125. try { h2.addMesh(m, color) } catch (e) {}
  126. })
  127. })
  128. )
  129. // 同样优化这个函数里的鼠标划出逻辑
  130. mesh.actionManager.registerAction(
  131. new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOutTrigger, function() {
  132. isPointerOverModel = false
  133. if (!clickParentRotate) { // 仅排除「手动暂停」的情况
  134. isRotating = true
  135. camera.useAutoRotationBehavior = true
  136. }
  137. var mesheses4 = transformNodex.getClassName() === 'Mesh' ? [transformNodex] : []
  138. mesheses4.forEach(m => {
  139. try { h2.removeMesh(m) } catch (e) {}
  140. })
  141. })
  142. )
  143. mesh.actionManager.registerAction(
  144. new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger, function() {
  145. try {
  146. cameraClick(transformNodex)
  147. } catch (error) {
  148. console.warn('点击回调执行失败:', error)
  149. }
  150. })
  151. )
  152. }
  153. }
  154. // 绑功能点(烟感)
  155. var smokeAlarms = []
  156. scene.transformNodes.forEach(function(node) {
  157. if (node.name.startsWith('smokealarm')) {
  158. smokeAlarms.push(node)
  159. }
  160. })
  161. var length = smokeAlarms.length
  162. console.log('以 smokealarm 开头的对象数量:', length)
  163. smokeAlarms.forEach(function(jk01, index) {
  164. console.log('smokeAlarms', jk01)
  165. var parts = jk01.name.split('smokealarm')
  166. jk01.nameID = parts.length > 1 ? `S${String(index + 1).padStart(3, '0')}` : 'S000'
  167. jk01.baojing = false
  168. prepareGroupButton2(jk01)
  169. })
  170. // 绑监控设备
  171. const cameraMeshes = []
  172. scene.transformNodes.forEach(function(node) {
  173. if (node.name.startsWith('有害生物去除器')) {
  174. cameraMeshes.push(node)
  175. }
  176. })
  177. const cameraCount = cameraMeshes.length
  178. console.log('以 有害生物去除器 开头的 Mesh 数量:', cameraCount)
  179. const colorBlue = new BABYLON.Color3(0, 0, 1)
  180. cameraMeshes.forEach((cam, index) => {
  181. cam.nameID = `cam_${String(index + 1).padStart(3, '0')}`
  182. prepareGroupButton2(cam, colorBlue)
  183. })
  184. // 绑档案柜
  185. const archivesCabinets = [];
  186. scene.transformNodes.forEach(function(node) {
  187. if (node.name.startsWith('档案柜')) {
  188. archivesCabinets.push(node);
  189. }
  190. });
  191. const archivesCabinetsCount = archivesCabinets.length;
  192. console.log('档案柜数量:', archivesCabinetsCount);
  193. if (archivesCabinets.length > 0) {
  194. const children = archivesCabinets[0]._children;
  195. const filteredChildren = children.filter(cam => cam.name !== "克隆_1");
  196. for (let i = filteredChildren.length - 1; i >= 0; i--) {
  197. const cam = filteredChildren[i];
  198. const paddedIndex = String(filteredChildren.length - i);
  199. cam.nameID = `cabinet-${paddedIndex}`;
  200. prepareGroupButton3(cam);
  201. }
  202. }
  203. var light = new BABYLON.HemisphericLight('HemiLight', new BABYLON.Vector3(0, 1, 0), scene)
  204. light.intensity = 2
  205. light.diffuse = new BABYLON.Color3(0.92, 0.92, 0.92)
  206. // 给vue页面传值,加载完成之后
  207. parent.getIframeLoading('false')
  208. }
  209. BABYLON.DracoCompression.Configuration.decoder.wasmUrl = './js/draco_wasm_wrapper_gltf.js'
  210. BABYLON.DracoCompression.Configuration.decoder.wasmBinaryUrl = './js/draco_decoder_gltf.wasm'
  211. BABYLON.DracoCompression.Configuration.decoder.fallbackUrl = './js/draco_decoder_gltf.js'
  212. // 3D模型页面(web3D/index.html)的createScene函数后添加适配逻辑
  213. var canvas = document.getElementById('renderCanvas')
  214. var engine = new BABYLON.Engine(canvas, true, { stencil: true })
  215. // ========== 新增:画布自适应iframe尺寸 ==========
  216. function resizeCanvas() {
  217. // 获取iframe的容器尺寸(如果iframe有父容器,也可以取父容器尺寸)
  218. const iframeWidth = window.innerWidth || document.documentElement.clientWidth
  219. const iframeHeight = window.innerHeight || document.documentElement.clientHeight
  220. // 设置canvas尺寸为iframe的100%(保证填满iframe,且跟随iframe缩放)
  221. canvas.width = iframeWidth
  222. canvas.height = iframeHeight
  223. // 通知引擎更新尺寸
  224. engine.resize()
  225. }
  226. // 初始化时执行一次
  227. resizeCanvas()
  228. // 监听窗口大小变化(iframe缩放时触发)
  229. window.addEventListener('resize', resizeCanvas)
  230. // createScene function that creates and return the scene
  231. var createScene = function() {
  232. engine.displayLoadingUI()
  233. var scene = new BABYLON.Scene(engine)
  234. camera = new BABYLON.ArcRotateCamera(
  235. 'Camera', 4.02, 0.98, 3.4,
  236. new BABYLON.Vector3(1.2, 0.08, 0.03),
  237. scene
  238. )
  239. camera.setTarget(new BABYLON.Vector3(0, 0, 0))
  240. camera.attachControl(canvas, true)
  241. // 相机参数(保持原优化)
  242. camera.lowerRadiusLimit = 0.1
  243. camera.upperRadiusLimit = 500
  244. camera.inertia = 0.1
  245. camera.minZ = 0.01
  246. camera.maxZ = 1000
  247. camera.fov = 1.0
  248. camera.useAutoRotationBehavior = isRotating // 初始启用自动旋转
  249. // 透明背景
  250. scene.clearColor = new BABYLON.Color4(0, 0, 0, 0)
  251. scene.activeCamera = camera
  252. scene.activeCamera.useInputToRestoreState = true
  253. var assetsManager = new BABYLON.AssetsManager(scene)
  254. // 加载GLB模型
  255. BABYLON.SceneLoader.LoadAssetContainerAsync('asset/', 'F5.glb', scene).then((container) => {
  256. container.addAllToScene()
  257. }).catch((error) => {
  258. console.error('加载模型时出错:', error)
  259. })
  260. var hdrTexture = new BABYLON.CubeTexture.CreateFromPrefilteredData('textures/environmentSpecular.env', scene)
  261. scene.environmentTexture = hdrTexture
  262. var spriteManagerPlayer = new BABYLON.SpriteManager('playerManager', './img/bl9.png', 10, {
  263. width: 100,
  264. height: 100
  265. }, scene)
  266. spriteManagerPlayer.isPickable = true
  267. scene.onPointerDown = function(evt) {
  268. var pickResult = scene.pickSprite(this.pointerX, this.pointerY)
  269. var pick = scene.pick(scene.pointerX, scene.pointerY)
  270. console.log('pick', pick.pickedPoint)
  271. if (pickResult.pickedSprite != null && pickResult.hit) {
  272. alert(pickResult.pickedSprite.name)
  273. }
  274. }
  275. assetsManager.load()
  276. drag = new BABYLON.PointerDragBehavior({
  277. dragPlaneNormal: new BABYLON.Vector3(0, 0, 1)
  278. })
  279. drag.validateDrag = (targetPosition) => {
  280. if (targetPosition.x > 10.5 || targetPosition.x < -10.5) return false
  281. if (targetPosition.z > 10.5 || targetPosition.z < -10.5) return false
  282. return oldtransformNodex != null
  283. }
  284. // GUI高亮层
  285. h1 = new BABYLON.HighlightLayer('hl1', scene)
  286. h2 = new BABYLON.HighlightLayer('hl2', scene)
  287. h3 = new BABYLON.HighlightLayer('hl3', scene)
  288. var step = 0.1
  289. var currentx = 1
  290. h1.blurHorizontalSize = 0.1
  291. scene.registerAfterRender(() => {
  292. h1.blurHorizontalSize = h1.blurVerticalSize + currentx
  293. // 报警高亮逻辑
  294. var nodealert = scene.getTransformNodeByName('yan')
  295. if (nodealert != null) {
  296. var mesheses3 = nodealert.getClassName() === 'TransformNode'
  297. ? nodealert.getChildMeshes(false)
  298. : [nodealert]
  299. mesheses3.forEach(mesh => {
  300. try {
  301. if (nodealert.baojing === true) {
  302. h3.addMesh(mesh, new BABYLON.Color3(1, 0, 0))
  303. } else {
  304. h3.removeMesh(mesh)
  305. }
  306. } catch (error) {}
  307. })
  308. }
  309. // 修复高亮动画速度控制
  310. if (currentx > 0.5) step *= -1
  311. if (currentx < 0) step *= -1
  312. currentx += step
  313. })
  314. return scene
  315. }
  316. var canvas = document.getElementById('renderCanvas')
  317. var engine = new BABYLON.Engine(canvas, true, { stencil: true })
  318. var scene = createScene()
  319. scene.autoClear = true
  320. scene.imageProcessingConfiguration.exposure = 1
  321. scene.imageProcessingConfiguration.contrast = 1
  322. scene.environmentIntensity = 0.4
  323. engine.runRenderLoop(function() {
  324. scene.render()
  325. })
  326. window.addEventListener('resize', function() {
  327. engine.resize()
  328. })
  329. // 设备点击回调
  330. function cameraClick(TheCamera) {
  331. window.parent.postMessage({
  332. type: 'cameraClick',
  333. data: TheCamera.nameID
  334. }, '*')
  335. }
  336. function archCabinetsClick(TheCamera) {
  337. window.parent.postMessage({
  338. type: 'archCabinetsClick',
  339. data: TheCamera.nameID
  340. }, '*')
  341. }
  342. // 报警状态处理
  343. function handleAlarm(deviceId, isAlarm) {
  344. var cl = new BABYLON.Color3(0, 0, 1)
  345. var c2 = new BABYLON.Color3(1, 0, 0)
  346. const targetDevice = scene.transformNodes.find(node => node.nameID === deviceId)
  347. if (targetDevice) {
  348. targetDevice.baojing = isAlarm
  349. var mesheses = targetDevice.getClassName() === 'TransformNode'
  350. ? targetDevice.getChildMeshes(false)
  351. : [targetDevice]
  352. mesheses.forEach(mesh => {
  353. if (isAlarm) {
  354. h2.addMesh(mesh, c2)
  355. } else {
  356. h2.removeMesh(mesh)
  357. h2.addMesh(mesh, cl)
  358. }
  359. })
  360. } else {
  361. console.log(`未找到设备 ID 为 ${deviceId} 的设备`)
  362. }
  363. }
  364. // 接收父页面消息(手动控制旋转)
  365. window.addEventListener('message', function(e) {
  366. if (e.data.type === 'deviceState') {
  367. console.log('ddd', e.data.data)
  368. const deviceData = e.data.data
  369. if (Array.isArray(deviceData)) {
  370. deviceData.forEach((device) => {
  371. handleAlarm(device.deviceId, device.isAlarm)
  372. })
  373. } else {
  374. handleAlarm(deviceData.deviceId, deviceData.isAlarm)
  375. }
  376. } else if (e.data.type === 'isGetRotate') {
  377. const isGetRotate = e.data.value
  378. console.log('isGetRotate:', isGetRotate)
  379. toggleAutoRotation(isGetRotate)
  380. }
  381. }, false)
  382. // 手动控制旋转开关(仅影响「手动暂停」状态)
  383. function toggleAutoRotation(isAutoRotating) {
  384. clickParentRotate = isAutoRotating // 标记:true=手动暂停,false=手动启用
  385. if (isAutoRotating) {
  386. // 手动暂停:无论鼠标是否在模型上,都停止旋转
  387. isRotating = false
  388. camera.useAutoRotationBehavior = false
  389. camera.angularSpeed = 0
  390. } else {
  391. // 手动启用:如果鼠标不在模型上,立即恢复旋转
  392. if (!isPointerOverModel) {
  393. isRotating = true
  394. camera.useAutoRotationBehavior = true
  395. }
  396. }
  397. }
  398. // 相机动画跳转
  399. function moveCameraTo(targetPreset) {
  400. var target = targetAngles[targetPreset]
  401. if (!target) return console.error('无效的视角预设')
  402. var camera = scene.activeCamera
  403. camera.panningInertia = 0
  404. var animationAlpha = new BABYLON.Animation(
  405. 'cameraAlphaAnimation',
  406. 'alpha',
  407. 60,
  408. BABYLON.Animation.ANIMATIONTYPE_FLOAT,
  409. BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
  410. )
  411. var animationBeta = new BABYLON.Animation(
  412. 'cameraBetaAnimation',
  413. 'beta',
  414. 60,
  415. BABYLON.Animation.ANIMATIONTYPE_FLOAT,
  416. BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
  417. )
  418. var animationRadius = new BABYLON.Animation(
  419. 'cameraRadiusAnimation',
  420. 'radius',
  421. 60,
  422. BABYLON.Animation.ANIMATIONTYPE_FLOAT,
  423. BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
  424. )
  425. var keysAlpha = [
  426. { frame: 0, value: camera.alpha },
  427. { frame: 120, value: target.alpha }
  428. ]
  429. var keysBeta = [
  430. { frame: 0, value: camera.beta },
  431. { frame: 120, value: target.beta }
  432. ]
  433. var keysRadius = [
  434. { frame: 0, value: camera.radius },
  435. { frame: 120, value: target.radius }
  436. ]
  437. animationAlpha.setKeys(keysAlpha)
  438. animationBeta.setKeys(keysBeta)
  439. animationRadius.setKeys(keysRadius)
  440. var easingFunction = new BABYLON.CubicEase()
  441. easingFunction.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT)
  442. animationAlpha.setEasingFunction(easingFunction)
  443. animationBeta.setEasingFunction(easingFunction)
  444. animationRadius.setEasingFunction(easingFunction)
  445. scene.beginDirectAnimation(camera, [animationAlpha, animationBeta, animationRadius], 0, 120, false, 1, function() {
  446. camera.panningInertia = 0.1
  447. toggleAutoRotation(false) // 动画结束后,恢复自动旋转(除非手动暂停)
  448. window.parent.postMessage({ type: 'autoRotationStatus', value: true }, '*')
  449. })
  450. }