use-echarts.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import type { EChartsOption } from 'echarts';
  2. import type EchartsUI from './echarts-ui.vue';
  3. import type { Ref } from 'vue';
  4. import { computed, nextTick, watch } from 'vue';
  5. import { usePreferences } from '@vben/preferences';
  6. import {
  7. tryOnUnmounted,
  8. useDebounceFn,
  9. useResizeObserver,
  10. useTimeoutFn,
  11. useWindowSize,
  12. } from '@vueuse/core';
  13. import echarts from './echarts';
  14. type EchartsUIType = typeof EchartsUI | undefined;
  15. type EchartsThemeType = 'dark' | 'light' | null;
  16. function useEcharts(chartRef: Ref<EchartsUIType>) {
  17. let chartInstance: echarts.ECharts | null = null;
  18. let cacheOptions: EChartsOption = {};
  19. const { isDark } = usePreferences();
  20. const { height, width } = useWindowSize();
  21. const resizeHandler: () => void = useDebounceFn(resize, 200);
  22. const getOptions = computed((): EChartsOption => {
  23. if (!isDark.value) {
  24. return cacheOptions;
  25. }
  26. return {
  27. backgroundColor: 'transparent',
  28. ...cacheOptions,
  29. };
  30. });
  31. const initCharts = (t?: EchartsThemeType) => {
  32. const el = chartRef?.value?.$el;
  33. if (!el) {
  34. return;
  35. }
  36. chartInstance = echarts.init(el, t || isDark.value ? 'dark' : null);
  37. return chartInstance;
  38. };
  39. const renderEcharts = (options: EChartsOption, clear = true) => {
  40. cacheOptions = options;
  41. return new Promise((resolve) => {
  42. if (chartRef.value?.offsetHeight === 0) {
  43. useTimeoutFn(() => {
  44. renderEcharts(getOptions.value);
  45. resolve(null);
  46. }, 30);
  47. return;
  48. }
  49. nextTick(() => {
  50. useTimeoutFn(() => {
  51. if (!chartInstance) {
  52. const instance = initCharts();
  53. if (!instance) return;
  54. }
  55. clear && chartInstance?.clear();
  56. chartInstance?.setOption(getOptions.value);
  57. resolve(null);
  58. }, 30);
  59. });
  60. });
  61. };
  62. function resize() {
  63. chartInstance?.resize({
  64. animation: {
  65. duration: 300,
  66. easing: 'quadraticIn',
  67. },
  68. });
  69. }
  70. watch([width, height], () => {
  71. resizeHandler?.();
  72. });
  73. useResizeObserver(chartRef as never, resizeHandler);
  74. watch(isDark, () => {
  75. if (chartInstance) {
  76. chartInstance.dispose();
  77. initCharts();
  78. renderEcharts(cacheOptions);
  79. resize();
  80. }
  81. });
  82. tryOnUnmounted(() => {
  83. // 销毁实例,释放资源
  84. chartInstance?.dispose();
  85. });
  86. return {
  87. renderEcharts,
  88. resize,
  89. };
  90. }
  91. export { useEcharts };
  92. export type { EchartsUIType };