useECharts.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // 导入 EChartsOption 类型
  2. import type { EChartsOption } from 'echarts';
  3. // 导入 Ref 类型
  4. import type { Ref } from 'vue';
  5. // 导入 useTimeoutFn 函数
  6. import { useTimeoutFn } from '/@/hooks/core/useTimeout';
  7. // 导入 tryOnUnmounted 函数
  8. import { tryOnUnmounted } from '@vueuse/core';
  9. // 导入 unref, nextTick, watch, computed, ref 函数
  10. import { unref, nextTick, watch, computed, ref } from 'vue';
  11. // 导入 useDebounceFn 函数
  12. import { useDebounceFn } from '@vueuse/core';
  13. // 导入 useEventListener 函数
  14. import { useEventListener } from '/@/hooks/event/useEventListener';
  15. // 导入 useBreakpoint 函数
  16. import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
  17. // 导入 echarts
  18. import echarts from '/@/utils/lib/echarts';
  19. // 导入 useRootSetting 函数
  20. import { useRootSetting } from '/@/hooks/setting/useRootSetting';
  21. // 定义 useECharts 函数,接收 elRef 和 theme 参数
  22. export function useECharts(
  23. elRef: Ref<HTMLDivElement>,
  24. theme: 'light' | 'dark' | 'default' = 'light'
  25. ) {
  26. // 获取 getDarkMode 函数
  27. const { getDarkMode } = useRootSetting();
  28. // 定义 chartInstance 变量,初始值为 null
  29. let chartInstance: echarts.ECharts | null = null;
  30. // 定义 resizeFn 变量,初始值为 resize 函数
  31. let resizeFn: Fn = resize;
  32. // 定义 cacheOptions 变量,初始值为空对象
  33. const cacheOptions = ref({}) as Ref<EChartsOption>;
  34. // 定义 removeResizeFn 变量,初始值为空函数
  35. let removeResizeFn: Fn = () => {};
  36. // 使用 useDebounceFn 函数对 resize 函数进行防抖处理,延迟 200ms
  37. resizeFn = useDebounceFn(resize, 200);
  38. // 定义 getOptions 计算属性
  39. const getOptions = computed(() => {
  40. // 如果不是暗黑模式,返回 cacheOptions 的值
  41. if (getDarkMode.value !== 'dark') {
  42. return cacheOptions.value as EChartsOption;
  43. }
  44. // 如果是暗黑模式,返回带有透明背景色的 cacheOptions 的值
  45. return {
  46. backgroundColor: 'transparent',
  47. ...cacheOptions.value,
  48. } as EChartsOption;
  49. });
  50. // 定义 initCharts 函数,接收 t 参数,默认值为 theme
  51. function initCharts(t = theme) {
  52. // 获取 elRef 的值
  53. const el = unref(elRef);
  54. // 如果 el 不存在,直接返回
  55. if (!el || !unref(el)) {
  56. return;
  57. }
  58. // 使用 echarts.init 初始化图表实例
  59. chartInstance = echarts.init(el, t);
  60. // 使用 useEventListener 监听窗口 resize 事件
  61. const { removeEvent } = useEventListener({
  62. el: window,
  63. name: 'resize',
  64. listener: resizeFn,
  65. });
  66. // 设置 removeResizeFn 为 removeEvent
  67. removeResizeFn = removeEvent;
  68. // 使用 useBreakpoint 获取屏幕宽度和枚举值
  69. const { widthRef, screenEnum } = useBreakpoint();
  70. // 如果屏幕宽度小于等于 MD 或者元素高度为 0,延迟 30ms 执行 resizeFn
  71. if (unref(widthRef) <= screenEnum.MD || el.offsetHeight === 0) {
  72. useTimeoutFn(() => {
  73. resizeFn();
  74. }, 30);
  75. }
  76. }
  77. // 定义 setOptions 函数,接收 options 和 clear 参数,默认值为 true
  78. function setOptions(options: EChartsOption, clear = true) {
  79. // 设置 cacheOptions 的值为 options
  80. cacheOptions.value = options;
  81. // 如果 elRef 的高度为 0,延迟 30ms 执行 setOptions 函数
  82. if (unref(elRef)?.offsetHeight === 0) {
  83. useTimeoutFn(() => {
  84. setOptions(unref(getOptions));
  85. }, 30);
  86. return;
  87. }
  88. // 在下一个 tick 执行
  89. nextTick(() => {
  90. // 延迟 30ms 执行
  91. useTimeoutFn(() => {
  92. // 如果 chartInstance 不存在,初始化图表实例
  93. if (!chartInstance) {
  94. initCharts(getDarkMode.value as 'default');
  95. if (!chartInstance) return;
  96. }
  97. // 如果 clear 为 true,清空图表实例
  98. clear && chartInstance?.clear();
  99. // 设置图表实例的选项
  100. chartInstance?.setOption(unref(getOptions));
  101. }, 30);
  102. });
  103. }
  104. // 定义 resize 函数
  105. function resize() {
  106. // 调用图表实例的 resize 方法
  107. chartInstance?.resize();
  108. }
  109. // 监听 getDarkMode.value 的变化
  110. watch(
  111. () => getDarkMode.value,
  112. (theme) => {
  113. // 如果图表实例存在
  114. if (chartInstance) {
  115. // 销毁图表实例
  116. chartInstance.dispose();
  117. // 重新初始化图表实例
  118. initCharts(theme as 'default');
  119. // 设置图表实例的选项
  120. setOptions(cacheOptions.value);
  121. }
  122. }
  123. );
  124. // 当组件卸载时执行
  125. tryOnUnmounted(() => {
  126. // 如果图表实例不存在,直接返回
  127. if (!chartInstance) return;
  128. // 移除 resize 事件监听
  129. removeResizeFn();
  130. // 销毁图表实例
  131. chartInstance.dispose();
  132. // 将 chartInstance 设置为 null
  133. chartInstance = null;
  134. });
  135. // 定义 getInstance 函数
  136. function getInstance(): echarts.ECharts | null {
  137. // 如果图表实例不存在,初始化图表实例
  138. if (!chartInstance) {
  139. initCharts(getDarkMode.value as 'default');
  140. }
  141. // 返回图表实例
  142. return chartInstance;
  143. }
  144. // 定义 destory 函数
  145. function destory() {
  146. // 如果图表实例不存在,直接返回
  147. if (!chartInstance) return;
  148. // 销毁图表实例
  149. chartInstance.dispose();
  150. // 将 chartInstance 设置为 null
  151. chartInstance = null;
  152. }
  153. // 返回对象,包含 setOptions, resize, echarts, getInstance, destory 方法
  154. return {
  155. setOptions,
  156. resize,
  157. echarts,
  158. getInstance,
  159. destory,
  160. };
  161. }