setup.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import { onActivated, onDeactivated, onUnmounted, SetupContext, onMounted } from "vue";
  2. import { debounce } from "@/utils/time"
  3. import { getTheme, ThemeEnum } from '@/common/config/theme';
  4. import * as echarts from 'echarts'
  5. // 创建 iframe 对象
  6. const createIframe = (parent: HTMLElement): HTMLIFrameElement => {
  7. const iframe = document.createElement('iframe');
  8. // 设置 iframe 样式
  9. iframe.style.cssText = 'position: absolute; z-index: -1000; left: 0; top: 0; width: 100%; height: 100%; border: 0; visibility: hidden; pointer-events: none;';
  10. // 添加 iframe 节点
  11. parent.appendChild(iframe);
  12. return iframe;
  13. }
  14. export function useEchart(el: HTMLElement) {
  15. const iframe = createIframe(el);
  16. const echartMap: echarts.ECharts[] = [];
  17. el.querySelectorAll('.echart__container').forEach((item) => {
  18. // 初始化图表
  19. const echart = echarts.init(item as HTMLElement);
  20. echartMap.push(echart);
  21. })
  22. // 显示加载动画
  23. const showLoading = (loading: boolean) => {
  24. if (loading) {
  25. echartMap.forEach((echart) => {
  26. echart.clear(); // 清空图表
  27. const theme = getTheme(); // 当前主题
  28. switch (theme.value) {
  29. case ThemeEnum.default:
  30. case ThemeEnum.dark:
  31. echart.showLoading({
  32. text: '加载中...',
  33. textColor: '#fff',
  34. color: 'rgba(255, 255, 255, 0.75)',
  35. maskColor: 'transparent',
  36. });
  37. break;
  38. default:
  39. echart.showLoading({
  40. text: '加载中...',
  41. maskColor: 'transparent',
  42. });
  43. }
  44. })
  45. }
  46. };
  47. // 图表配置项
  48. const setOptions = (options: echarts.EChartsOption[], notMerge = false) => {
  49. options.forEach((opt, i) => {
  50. echartMap[i].setOption(opt, notMerge);
  51. echartMap[i].hideLoading();
  52. });
  53. };
  54. const onresize = () => {
  55. // 防抖函数待优化,同时调用多次timeoutId可能相同,导致后面的覆盖前面
  56. debounce(() => {
  57. // 重置图表大小
  58. echartMap.forEach((echart) => {
  59. echart.resize && echart.resize();
  60. })
  61. }, 50);
  62. };
  63. // 键盘上下左右键控制图表
  64. const onKeyup = (e: KeyboardEvent) => {
  65. // echartMap.forEach((chart) => {
  66. // const datazoom = chart.getOption().dataZoom as echarts.DataZoomComponentOption[];
  67. // if (datazoom && datazoom.length) {
  68. // const start = datazoom[0].start!;
  69. // const end = datazoom[0].end!;
  70. // switch (e.key) {
  71. // case 'ArrowLeft':
  72. // if (start > 0) {
  73. // chart.setOption({
  74. // dataZoom: [
  75. // {
  76. // start: start - 1,
  77. // end: end - 1,
  78. // }
  79. // ]
  80. // });
  81. // }
  82. // break;
  83. // case 'ArrowUp':
  84. // console.log('上');
  85. // break;
  86. // case 'ArrowRight':
  87. // if (end < 100) {
  88. // chart.setOption({
  89. // dataZoom: [
  90. // {
  91. // start: start + 1,
  92. // end: end + 1,
  93. // }
  94. // ]
  95. // });
  96. // }
  97. // break;
  98. // case 'ArrowDown':
  99. // console.log('下');
  100. // break;
  101. // default:
  102. // console.log(e);
  103. // }
  104. // }
  105. // });
  106. };
  107. const addEventListener = () => {
  108. // 监听 iframe 变化重置图表尺寸
  109. iframe.contentWindow?.addEventListener('resize', onresize);
  110. // 监听键盘事件
  111. document.addEventListener('keyup', onKeyup);
  112. }
  113. const removeEventListener = () => {
  114. // 移除 iframe 监听事件
  115. iframe.contentWindow?.removeEventListener('resize', onresize);
  116. // 移除键盘监听事件
  117. document.removeEventListener('keyup', onKeyup);
  118. }
  119. addEventListener();
  120. onUnmounted(() => {
  121. echartMap.forEach((echart) => {
  122. echart.dispose();
  123. })
  124. removeEventListener();
  125. })
  126. // 针对 keepalive 缓存组件
  127. onActivated(() => {
  128. addEventListener();
  129. })
  130. // 针对 keepalive 缓存组件
  131. onDeactivated(() => {
  132. removeEventListener();
  133. })
  134. return {
  135. setOptions,
  136. showLoading,
  137. }
  138. }