useEcharts.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
  2. import * as echarts from 'echarts';
  3. import { useResizeObserver } from '@vueuse/core';
  4. /**
  5. * ECharts Hook
  6. * @param containerRef 图表容器 Ref
  7. * @param options 图表配置 Ref
  8. * @param theme 主题配置(可选)
  9. * @param autoResize 是否自动响应容器大小变化(默认 true)
  10. */
  11. export function useECharts(
  12. containerRef,
  13. options,
  14. theme = 'macarons',
  15. autoResize = true
  16. ) {
  17. const chartInstance = ref(null);
  18. const resizeObserver = ref(null);
  19. let eventQueue = []
  20. // 初始化图表
  21. const init = () => {
  22. if (!containerRef.value) return;
  23. dispose();
  24. chartInstance.value = markRaw(echarts.init(containerRef.value, theme))
  25. chartInstance.value.setOption(options.value);
  26. eventQueue = eventQueue.filter((handler) => {
  27. handler()
  28. return false
  29. })
  30. // 初始化 resize 监听
  31. if (autoResize) {
  32. setupResizeObserver();
  33. }
  34. };
  35. // 设置 resize 监听
  36. const setupResizeObserver = () => {
  37. if (!containerRef.value) return;
  38. resizeObserver.value = useResizeObserver(containerRef.value, () => {
  39. resize();
  40. });
  41. };
  42. // 销毁图表
  43. const dispose = () => {
  44. // 移除 resize 监听
  45. if (resizeObserver.value) {
  46. resizeObserver.value.stop();
  47. resizeObserver.value = null;
  48. }
  49. // 销毁图表实例
  50. if (chartInstance.value && !chartInstance.value.isDisposed()) {
  51. chartInstance.value.dispose();
  52. chartInstance.value = null;
  53. }
  54. };
  55. // 重置图表
  56. const reset = () => {
  57. dispose();
  58. init();
  59. };
  60. // 手动触发 resize
  61. const resize = () => {
  62. if (chartInstance.value) {
  63. try {
  64. chartInstance.value.resize();
  65. } catch (error) {
  66. console.error('ECharts resize 失败:', error);
  67. }
  68. }
  69. };
  70. const bindEvent = (eventName, callback) => {
  71. eventQueue.push(() => chartInstance.value.getZr().on(eventName, callback))
  72. return result
  73. }
  74. // 监听 options 变化
  75. watch(options, (newOptions) => {
  76. if (chartInstance.value) {
  77. chartInstance.value.setOption(newOptions);
  78. }
  79. }, { deep: true, immediate: true });
  80. // 组件生命周期
  81. onMounted(() => {
  82. init()
  83. });
  84. onBeforeUnmount(() => dispose());
  85. const result = {
  86. instance: chartInstance,
  87. init,
  88. dispose,
  89. reset,
  90. resize,
  91. bindEvent
  92. };
  93. return result
  94. }