useEcharts.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import type { Ref } from "vue";
  2. import type { EChartsOption } from "echarts";
  3. import * as echarts from "echarts";
  4. import { unref, nextTick, watch, computed, ref } from "vue";
  5. import { tryOnUnmounted, useDebounceFn, useEventListener } from "@vueuse/core";
  6. export function useEcharts(
  7. elRef: Ref<HTMLElement>,
  8. theme: "default" | "dark" | "light" = "default"
  9. ) {
  10. let chartInstance: echarts.ECharts | null = null;
  11. let resizeFn: () => void = resize;
  12. const cacheOptions = ref({});
  13. let removeResizeFn: () => void;
  14. const getOptions = computed(() => {
  15. return cacheOptions.value;
  16. });
  17. resizeFn = useDebounceFn(resize, 200);
  18. function resize() {
  19. chartInstance?.resize({
  20. animation: {
  21. duration: 300,
  22. easing: "quadraticIn",
  23. },
  24. });
  25. }
  26. function initCharts(t = theme) {
  27. const el = unref(elRef);
  28. if (!el || !unref(el)) {
  29. return;
  30. }
  31. chartInstance = echarts.init(el, t);
  32. const removeEvent = useEventListener(window, "resize", resizeFn);
  33. removeResizeFn = removeEvent;
  34. }
  35. function setOptions(options: EChartsOption, clear = false) {
  36. cacheOptions.value = options;
  37. return new Promise((resolve) => {
  38. if (unref(elRef)?.offsetHeight === 0) {
  39. setTimeout(() => {
  40. setOptions(unref(getOptions));
  41. resolve(null);
  42. }, 30);
  43. }
  44. nextTick(() => {
  45. setTimeout(() => {
  46. if (!chartInstance) {
  47. initCharts("default");
  48. if (!chartInstance) return;
  49. }
  50. clear && chartInstance?.clear();
  51. chartInstance?.setOption(unref(getOptions));
  52. resolve(null);
  53. }, 30);
  54. });
  55. });
  56. }
  57. watch(
  58. () => theme,
  59. (theme) => {
  60. if (chartInstance) {
  61. chartInstance.dispose();
  62. initCharts(theme as "default");
  63. setOptions(cacheOptions.value);
  64. }
  65. }
  66. );
  67. tryOnUnmounted(() => {
  68. if (!chartInstance) return;
  69. removeResizeFn();
  70. chartInstance.dispose();
  71. chartInstance = null;
  72. });
  73. function getInstance(): echarts.ECharts | null {
  74. if (!chartInstance) {
  75. initCharts("default");
  76. }
  77. return chartInstance;
  78. }
  79. return {
  80. setOptions,
  81. resize,
  82. echarts,
  83. getInstance,
  84. };
  85. }