黄陂项目
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.

500 lines
16 KiB

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
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. // createScene function that creates and return the scene
  213. var createScene = function() {
  214. engine.displayLoadingUI()
  215. var scene = new BABYLON.Scene(engine)
  216. camera = new BABYLON.ArcRotateCamera(
  217. 'Camera', 4.02, 0.98, 2.6,
  218. new BABYLON.Vector3(1.2, 0.08, 0.03),
  219. scene
  220. )
  221. camera.setTarget(new BABYLON.Vector3(0, 0, 0))
  222. camera.attachControl(canvas, true)
  223. // 相机参数(保持原优化)
  224. camera.lowerRadiusLimit = 0.1
  225. camera.upperRadiusLimit = 500
  226. camera.inertia = 0.1
  227. camera.minZ = 0.01
  228. camera.maxZ = 1000
  229. camera.fov = 0.8
  230. camera.useAutoRotationBehavior = isRotating // 初始启用自动旋转
  231. // 透明背景
  232. scene.clearColor = new BABYLON.Color4(0, 0, 0, 0)
  233. scene.activeCamera = camera
  234. scene.activeCamera.useInputToRestoreState = true
  235. var assetsManager = new BABYLON.AssetsManager(scene)
  236. // 加载GLB模型
  237. BABYLON.SceneLoader.LoadAssetContainerAsync('asset/', 'F5.glb', scene).then((container) => {
  238. container.addAllToScene()
  239. }).catch((error) => {
  240. console.error('加载模型时出错:', error)
  241. })
  242. var hdrTexture = new BABYLON.CubeTexture.CreateFromPrefilteredData('textures/environmentSpecular.env', scene)
  243. scene.environmentTexture = hdrTexture
  244. var spriteManagerPlayer = new BABYLON.SpriteManager('playerManager', './img/bl9.png', 10, {
  245. width: 100,
  246. height: 100
  247. }, scene)
  248. spriteManagerPlayer.isPickable = true
  249. scene.onPointerDown = function(evt) {
  250. var pickResult = scene.pickSprite(this.pointerX, this.pointerY)
  251. var pick = scene.pick(scene.pointerX, scene.pointerY)
  252. console.log('pick', pick.pickedPoint)
  253. if (pickResult.pickedSprite != null && pickResult.hit) {
  254. alert(pickResult.pickedSprite.name)
  255. }
  256. }
  257. assetsManager.load()
  258. drag = new BABYLON.PointerDragBehavior({
  259. dragPlaneNormal: new BABYLON.Vector3(0, 0, 1)
  260. })
  261. drag.validateDrag = (targetPosition) => {
  262. if (targetPosition.x > 10.5 || targetPosition.x < -10.5) return false
  263. if (targetPosition.z > 10.5 || targetPosition.z < -10.5) return false
  264. return oldtransformNodex != null
  265. }
  266. // GUI高亮层
  267. h1 = new BABYLON.HighlightLayer('hl1', scene)
  268. h2 = new BABYLON.HighlightLayer('hl2', scene)
  269. h3 = new BABYLON.HighlightLayer('hl3', scene)
  270. var step = 0.1
  271. var currentx = 1
  272. h1.blurHorizontalSize = 0.1
  273. scene.registerAfterRender(() => {
  274. h1.blurHorizontalSize = h1.blurVerticalSize + currentx
  275. // 报警高亮逻辑
  276. var nodealert = scene.getTransformNodeByName('yan')
  277. if (nodealert != null) {
  278. var mesheses3 = nodealert.getClassName() === 'TransformNode'
  279. ? nodealert.getChildMeshes(false)
  280. : [nodealert]
  281. mesheses3.forEach(mesh => {
  282. try {
  283. if (nodealert.baojing === true) {
  284. h3.addMesh(mesh, new BABYLON.Color3(1, 0, 0))
  285. } else {
  286. h3.removeMesh(mesh)
  287. }
  288. } catch (error) {}
  289. })
  290. }
  291. // 修复高亮动画速度控制
  292. if (currentx > 0.5) step *= -1
  293. if (currentx < 0) step *= -1
  294. currentx += step
  295. })
  296. return scene
  297. }
  298. var canvas = document.getElementById('renderCanvas')
  299. var engine = new BABYLON.Engine(canvas, true, { stencil: true })
  300. var scene = createScene()
  301. scene.autoClear = true
  302. scene.imageProcessingConfiguration.exposure = 1
  303. scene.imageProcessingConfiguration.contrast = 1
  304. scene.environmentIntensity = 0.4
  305. engine.runRenderLoop(function() {
  306. scene.render()
  307. })
  308. window.addEventListener('resize', function() {
  309. engine.resize()
  310. })
  311. // 设备点击回调
  312. function cameraClick(TheCamera) {
  313. window.parent.postMessage({
  314. type: 'cameraClick',
  315. data: TheCamera.nameID
  316. }, '*')
  317. }
  318. function archCabinetsClick(TheCamera) {
  319. window.parent.postMessage({
  320. type: 'archCabinetsClick',
  321. data: TheCamera.nameID
  322. }, '*')
  323. }
  324. // 报警状态处理
  325. function handleAlarm(deviceId, isAlarm) {
  326. var cl = new BABYLON.Color3(0, 0, 1)
  327. var c2 = new BABYLON.Color3(1, 0, 0)
  328. const targetDevice = scene.transformNodes.find(node => node.nameID === deviceId)
  329. if (targetDevice) {
  330. targetDevice.baojing = isAlarm
  331. var mesheses = targetDevice.getClassName() === 'TransformNode'
  332. ? targetDevice.getChildMeshes(false)
  333. : [targetDevice]
  334. mesheses.forEach(mesh => {
  335. if (isAlarm) {
  336. h2.addMesh(mesh, c2)
  337. } else {
  338. h2.removeMesh(mesh)
  339. h2.addMesh(mesh, cl)
  340. }
  341. })
  342. } else {
  343. console.log(`未找到设备 ID 为 ${deviceId} 的设备`)
  344. }
  345. }
  346. // 接收父页面消息(手动控制旋转)
  347. window.addEventListener('message', function(e) {
  348. if (e.data.type === 'deviceState') {
  349. console.log('ddd', e.data.data)
  350. const deviceData = e.data.data
  351. if (Array.isArray(deviceData)) {
  352. deviceData.forEach((device) => {
  353. handleAlarm(device.deviceId, device.isAlarm)
  354. })
  355. } else {
  356. handleAlarm(deviceData.deviceId, deviceData.isAlarm)
  357. }
  358. } else if (e.data.type === 'isGetRotate') {
  359. const isGetRotate = e.data.value
  360. console.log('isGetRotate:', isGetRotate)
  361. toggleAutoRotation(isGetRotate)
  362. }
  363. }, false)
  364. // 手动控制旋转开关(仅影响「手动暂停」状态)
  365. function toggleAutoRotation(isAutoRotating) {
  366. clickParentRotate = isAutoRotating // 标记:true=手动暂停,false=手动启用
  367. if (isAutoRotating) {
  368. // 手动暂停:无论鼠标是否在模型上,都停止旋转
  369. isRotating = false
  370. camera.useAutoRotationBehavior = false
  371. camera.angularSpeed = 0
  372. } else {
  373. // 手动启用:如果鼠标不在模型上,立即恢复旋转
  374. if (!isPointerOverModel) {
  375. isRotating = true
  376. camera.useAutoRotationBehavior = true
  377. }
  378. }
  379. }
  380. // 相机动画跳转
  381. function moveCameraTo(targetPreset) {
  382. var target = targetAngles[targetPreset]
  383. if (!target) return console.error('无效的视角预设')
  384. var camera = scene.activeCamera
  385. camera.panningInertia = 0
  386. var animationAlpha = new BABYLON.Animation(
  387. 'cameraAlphaAnimation',
  388. 'alpha',
  389. 60,
  390. BABYLON.Animation.ANIMATIONTYPE_FLOAT,
  391. BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
  392. )
  393. var animationBeta = new BABYLON.Animation(
  394. 'cameraBetaAnimation',
  395. 'beta',
  396. 60,
  397. BABYLON.Animation.ANIMATIONTYPE_FLOAT,
  398. BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
  399. )
  400. var animationRadius = new BABYLON.Animation(
  401. 'cameraRadiusAnimation',
  402. 'radius',
  403. 60,
  404. BABYLON.Animation.ANIMATIONTYPE_FLOAT,
  405. BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
  406. )
  407. var keysAlpha = [
  408. { frame: 0, value: camera.alpha },
  409. { frame: 120, value: target.alpha }
  410. ]
  411. var keysBeta = [
  412. { frame: 0, value: camera.beta },
  413. { frame: 120, value: target.beta }
  414. ]
  415. var keysRadius = [
  416. { frame: 0, value: camera.radius },
  417. { frame: 120, value: target.radius }
  418. ]
  419. animationAlpha.setKeys(keysAlpha)
  420. animationBeta.setKeys(keysBeta)
  421. animationRadius.setKeys(keysRadius)
  422. var easingFunction = new BABYLON.CubicEase()
  423. easingFunction.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT)
  424. animationAlpha.setEasingFunction(easingFunction)
  425. animationBeta.setEasingFunction(easingFunction)
  426. animationRadius.setEasingFunction(easingFunction)
  427. scene.beginDirectAnimation(camera, [animationAlpha, animationBeta, animationRadius], 0, 120, false, 1, function() {
  428. camera.panningInertia = 0.1
  429. toggleAutoRotation(false) // 动画结束后,恢复自动旋转(除非手动暂停)
  430. window.parent.postMessage({ type: 'autoRotationStatus', value: true }, '*')
  431. })
  432. }