概述

就之前的路径动画和开关动画结合,实现效果:点击开关->播放开门动画->0.5s后,按钮回到初始位置->5s后,播放关门动画。连续点击开关,推拉门会一直保持开着的状态,停止点击开关5s后,推拉门会关上。

最终效果录屏

开关-门联动动画.mp4

代码实现

deepblueJson.js

  1. /* deepblueJson.js */
  2. const deepblueLeafJson = [
  3. {
  4. "czmObject": {
  5. "xbsjType": "Tileset",
  6. "xbsjGuid": "a341be0f-d5df-48c3-9c36-8af547e64000",
  7. "name": "室内",
  8. "url": "...", // 此处为 室内模型 3dtiles数据地址
  9. "xbsjPosition": [
  10. 2.044452086968357,
  11. 0.6398399028959787,
  12. 271.22052428840794
  13. ],
  14. "xbsjUseOriginTransform": false,
  15. "xbsjClippingPlanes": {},
  16. "xbsjCustomShader": {}
  17. }
  18. }
  19. ];
  20. export default deepblueLeafJson;

switchJson.js

  1. /* switchJson.js */
  2. const switchJson = [
  3. {
  4. "ref": "switch0",
  5. "czmObject": {
  6. "xbsjType": "Tileset",
  7. "xbsjGuid": "b7a4c6d4-23f3-474e-a828-f34264e40416",
  8. "name": "前台-开关",
  9. "url": `...`, // 此处为 开关模型 3dtiles数据地址
  10. "xbsjPosition": [
  11. 2.04445046799674,
  12. 0.6398405354461021,
  13. 276.1871900601074
  14. ],
  15. "xbsjRotation": [
  16. 0,
  17. -0.08726646259971647,
  18. 0
  19. ],
  20. "xbsjScale": [
  21. 0.05,
  22. 0.05,
  23. 0.05
  24. ],
  25. "xbsjUseOriginTransform": false,
  26. "xbsjClippingPlanes": {},
  27. "xbsjCustomShader": {}
  28. }
  29. },
  30. {
  31. "ref": "switch1",
  32. "czmObject": {
  33. "xbsjType": "Tileset",
  34. "xbsjGuid": "f1e7c69f-dc49-4ae1-a7f4-e06de262b81a",
  35. "name": "东走廊-北开关",
  36. "url": `...`, // 此处为 开关模型 3dtiles数据地址
  37. "xbsjPosition": [
  38. 2.0444537081870697,
  39. 0.6398405398321795,
  40. 276.0500531178269
  41. ],
  42. "xbsjRotation": [
  43. 0,
  44. 0.08726646259971647,
  45. 0
  46. ],
  47. "xbsjScale": [
  48. 0.05,
  49. 0.05,
  50. 0.05
  51. ],
  52. "xbsjUseOriginTransform": false,
  53. "xbsjClippingPlanes": {},
  54. "xbsjCustomShader": {}
  55. }
  56. },
  57. {
  58. "ref": "switch2",
  59. "czmObject": {
  60. "xbsjType": "Tileset",
  61. "xbsjGuid": "a9ff6500-db41-4ac4-b625-ee1d230ca368",
  62. "name": "东走廊-南开关",
  63. "url": `...`, // 此处为 开关模型 3dtiles数据地址
  64. "xbsjPosition": [
  65. 2.044453705485192,
  66. 0.6398378621520856,
  67. 276.0524963624675
  68. ],
  69. "xbsjRotation": [
  70. 0,
  71. 0.08726646259971647,
  72. 0
  73. ],
  74. "xbsjScale": [
  75. 0.05,
  76. 0.05,
  77. 0.05
  78. ],
  79. "xbsjUseOriginTransform": false,
  80. "xbsjClippingPlanes": {},
  81. "xbsjCustomShader": {}
  82. }
  83. },
  84. {
  85. "ref": "switch3",
  86. "czmObject": {
  87. "xbsjType": "Tileset",
  88. "xbsjGuid": "788772f1-7700-44fe-b88a-727125fb9574",
  89. "name": "展厅-开关",
  90. "url": `...`, // 此处为 开关模型 3dtiles数据地址
  91. "xbsjPosition": [
  92. 2.0444540754666938,
  93. 0.6398411828712737,
  94. 276.1240135896563
  95. ],
  96. "xbsjRotation": [
  97. 0,
  98. 0.08726646259971647,
  99. 0
  100. ],
  101. "xbsjScale": [
  102. 0.03,
  103. 0.03,
  104. 0.03
  105. ],
  106. "xbsjUseOriginTransform": false,
  107. "xbsjClippingPlanes": {},
  108. "xbsjCustomShader": {}
  109. }
  110. }
  111. ];
  112. export default switchJson;

glassDoorJson.js

  1. /* glassDoorJson.js */
  2. const glassDoorJson = [
  3. {
  4. "ref": "model1",
  5. "czmObject": {
  6. "xbsjType": "Tileset",
  7. "xbsjGuid": "73ed68f3-1dc4-40e7-bddb-50a3e7be4bed",
  8. "name": "玻璃门",
  9. "url": "...", // 此处为 玻璃门模型 3dtiles数据地址
  10. "xbsjPosition": [
  11. 2.0444504835730815,
  12. 0.6398409689910697,
  13. 273.0587282572857
  14. ],
  15. "xbsjUseOriginTransform": false,
  16. "xbsjClippingPlanes": {},
  17. "xbsjCustomShader": {}
  18. }
  19. },{
  20. "ref": "path1",
  21. "czmObject": {
  22. "xbsjType": "Path",
  23. "xbsjGuid": "791ba4ac-a022-4f04-8e36-66dff64aa24d",
  24. "name": "路径动画",
  25. "positions": [
  26. [
  27. 2.0444504835730815,
  28. 0.6398409689910697,
  29. 273.0587282572857
  30. ],
  31. [
  32. 2.0444504835730815,
  33. 0.639841101,
  34. 273.0587282572857
  35. ]
  36. ],
  37. "rotations": [
  38. [
  39. 0,
  40. 0,
  41. 0
  42. ],
  43. [
  44. 0,
  45. 0,
  46. 0
  47. ]
  48. ],
  49. "currentSpeed": 1,
  50. "playing": false
  51. }
  52. },{
  53. "ref": "path2",
  54. "czmObject": {
  55. "xbsjType": "Path",
  56. "xbsjGuid": "0a1e9f7e-18fb-4996-bd1a-1303a2fcc6cc",
  57. "name": "路径动画",
  58. "positions": [
  59. [
  60. 2.0444504835730815,
  61. 0.639841101,
  62. 273.0587282572857
  63. ],
  64. [
  65. 2.0444504835730815,
  66. 0.6398409689910697,
  67. 273.0587282572857
  68. ]
  69. ],
  70. "rotations": [
  71. [
  72. 0,
  73. 0,
  74. 0
  75. ],
  76. [
  77. 0,
  78. 0,
  79. 0
  80. ]
  81. ],
  82. "currentSpeed": 1,
  83. "playing": false
  84. }
  85. }
  86. ];
  87. export default glassDoorJson;

deepblue_ani.js

注意连续点击按钮时,不应该出现开/关门动画重复从最初位置播放的情况:

  • 使用变量控制开/关门动画的执行
  • 关门动画和开关动画的定时器在每次动画执行前要清空 ```javascript / deepblue_ani.js /

let openDoor = false; let closeTimer = null; // 关门动画定时器 let switchTimer = null; // 开关动画定时器

// 室内模型-玻璃门 开门 动画 function openDoorAnimation (earth) { const model1 = earth.sceneTree.$refs.model1.czmObject; const path1 = earth.sceneTree.$refs.path1.czmObject; if (model1.xbsjPosition[1] !== path1.positions[1][1] && openDoor) { // 开关按下并且推拉门没有移动到路径终点时,执行开门动画 path1.playing = true; XE.MVVM.watch(path1, ‘currentPosition’, position => { model1.xbsjPosition = […position]; }); } }

// 室内模型-玻璃门 关门 动画 function closeDoorAnimation (earth) { const model1 = earth.sceneTree.$refs.model1.czmObject; const path2 = earth.sceneTree.$refs.path2.czmObject; if(closeTimer) { // 关门动画开始前,清空定时器,避免出现重复播放关门动画的情况 clearTimeout(closeTimer) } if (model1.xbsjPosition[1] !== path2.positions[1][1] && !openDoor) { // 开关没被按下并且推拉门没有移动到路径终点时,执行关门动画 closeTimer = setTimeout(()=>{ path2.playing = true; XE.MVVM.watch(path2, ‘currentPosition’, position2 => { model1.xbsjPosition = […position2]; }) }, 5000) } }

// 室内模型-开关 按下动画 function switchAnimation (earth) { const switch1 = earth.sceneTree.$refs.switch1.czmObject; console.log(switch1.xbsjPosition[0] / Math.PI * 180); switch1.onclick = () => { if (switchTimer) { clearTimeout(switchTimer) } switch1.xbsjRotation = [ 0, 0.08726646259971647, 0]; switch1.xbsjPosition = [2.044450471145981, 0.6398405354461021, 276.1871900601074]; // 开关按下,执行开门动画 openDoor = true; openDoorAnimation(earth); switchTimer = setTimeout(()=>{ switch1.xbsjRotation = [ 0, -0.08726646259971647, 0]; switch1.xbsjPosition = [2.04445046799674, 0.6398405354461021, 276.1871900601074] // 开关恢复原位,执行关门动画 openDoor = false; closeDoorAnimation(earth); }, 500);

} }

export default switchAnimation;

  1. <a name="tL1W9"></a>
  2. ### index.js
  3. ```javascript
  4. /* index.js */
  5. import deepblueLeafJson from '@/constant/deepblueJson'; // 引入路径可根据实际情况调整
  6. import switchJson from '@/constant/switchJson'; // 引入路径可根据实际情况调整
  7. import glassDoorJson from '@/constant/glassDoorJson'; // 引入路径可根据实际情况调整
  8. import switchAnimation from '@/pages/DigitalTwin/deepblue_ani'; // 引入路径可根据实际情况调整
  9. class animationDemo extends Component{
  10. constructor(props) {
  11. super(props);
  12. this.earth = null;
  13. },
  14. componentDidMount() {
  15. XE.ready().then(()=>{
  16. // 加载标绘插件 js
  17. ...
  18. }).then(()=>{
  19. this.startUp();
  20. })
  21. },
  22. startUp = ()=>{
  23. // 创建 Earth实例
  24. this.earth = new XE.Earth("earthContainer");
  25. // 开启拾取(鼠标点击事件)
  26. this.earth.interaction.picking.enabled = true;
  27. // 通过JSON配置创建节点
  28. this.earth.sceneTree.root.children.push(...deepblueLeafJson, ...switchJson, ...glassDoorJson);
  29. switchAnimation(this.earth);
  30. }
  31. return (
  32. <div id="earthContainer"></div>
  33. )
  34. }
  35. export default animationDemo;