dedustSVG.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <template>
  2. <!-- 二维模型:除尘风机(复用掘进工作面模型包 tun-face-2d);本组件只保留业务驱动 -->
  3. <SvgModelViewer ref="viewerRef" model-id="tun-face-2d" :identify="identify" />
  4. </template>
  5. <script setup lang="ts">
  6. import { onBeforeUnmount, ref, watch } from 'vue';
  7. import SvgModelViewer from '/@/components/vent/SvgModelViewer.vue';
  8. import { useEngineAnim } from '/@/utils/svg-model/useEngineAnim';
  9. withDefaults(
  10. defineProps<{
  11. /** 组件唯一标识符,提供后可以确保多个组件复用时的元素定位依旧准确 */
  12. identify?: string;
  13. }>(),
  14. { identify: '' }
  15. );
  16. /**
  17. * 除尘风机页面复用掘进工作面模型:模型整体照常显示,但 3 个流动箭头不播放、直接隐藏。
  18. * 驱动保留 animate(running) 开关:true → 箭头显示并循环流动,false(默认)→ 箭头隐藏。
  19. */
  20. const ARROW_IDS = ['auto_anim_0', 'auto_anim_1', 'auto_anim_2'];
  21. /** 一轮循环时长(10 帧,按观感可调) */
  22. const LOOP_PERIOD_MS = 2200;
  23. const viewerRef = ref<any>(null);
  24. const { engine } = useEngineAnim(viewerRef);
  25. let anims: Animation[] = [];
  26. let running = false;
  27. function stop() {
  28. anims.forEach((a) => {
  29. try {
  30. a.cancel();
  31. } catch (e) {
  32. /* ignore */
  33. }
  34. });
  35. anims = [];
  36. }
  37. function setVisible(visible: boolean) {
  38. const eng = engine.value;
  39. if (!eng) return;
  40. ARROW_IDS.forEach((id) => {
  41. const el = eng.getElement(id) as HTMLElement | undefined;
  42. if (el) el.style.display = visible ? '' : 'none';
  43. });
  44. }
  45. /** 开始循环流动:帧序列本身就是一段完整的小动画,直接循环播放 */
  46. function start() {
  47. stop();
  48. const eng = engine.value;
  49. if (!eng) return;
  50. ARROW_IDS.forEach((id) => {
  51. const el = eng.getElement(id);
  52. const frames = eng.getElementInfo(id)?.frames;
  53. if (!el || !frames || frames.length < 2) return;
  54. // model.json 里这排箭头的首尾位移 = 相邻箭头图案间距,循环回绕时正好落到相邻箭头上
  55. const keyframes = frames.map((transform) => ({ transform }));
  56. const anim = (el as HTMLElement).animate(keyframes, {
  57. duration: LOOP_PERIOD_MS,
  58. iterations: Infinity,
  59. easing: 'linear',
  60. fill: 'both',
  61. });
  62. anims.push(anim);
  63. });
  64. }
  65. /**
  66. * 除尘风机二维模型开关
  67. *
  68. * @param flag 是否播放箭头:false(默认)→ 箭头隐藏;true → 箭头显示并循环流动
  69. */
  70. function animate(flag: boolean = false) {
  71. running = flag;
  72. setVisible(flag);
  73. if (flag) start();
  74. else stop();
  75. }
  76. watch(engine, (eng) => {
  77. if (!eng) return;
  78. if (running) {
  79. setVisible(true);
  80. start();
  81. } else {
  82. setVisible(false);
  83. }
  84. });
  85. onBeforeUnmount(() => {
  86. stop();
  87. });
  88. defineExpose({ animate });
  89. </script>