index.vue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <template>
  2. <div ref="canvas" class="canvas" />
  3. </template>
  4. <script setup lang="ts" name="Chart">
  5. import ElementResizeDetectorMaker from 'element-resize-detector';
  6. import { autoToolTip } from './echarts_auto_tooltip';
  7. import * as echarts from 'echarts';
  8. import { onUnmounted } from 'vue';
  9. interface Props {
  10. option: object;
  11. rotation?: boolean;
  12. chartClick?: Function;
  13. legendChange?: Function;
  14. }
  15. const props = withDefaults(defineProps<Props>(), {
  16. rotation: false,
  17. legendChange: () => {}
  18. });
  19. const emits = defineEmits(['ready', 'click']);
  20. // 渲染容器
  21. const canvas = ref<HTMLElement>();
  22. // echarts
  23. const myChart = shallowRef(null);
  24. // 加载状态
  25. let loaded = ref(false);
  26. watch(
  27. props.option,
  28. () => {
  29. if (Object.keys(props.option).length !== 0) {
  30. if (loaded.value && !!myChart.value) {
  31. myChart.value.setOption(props.option, true);
  32. } else {
  33. load();
  34. }
  35. } else if (!!myChart.value) {
  36. myChart.value.clear();
  37. }
  38. },
  39. {
  40. deep: true
  41. }
  42. );
  43. // 加载事件
  44. const load = () => {
  45. if (!myChart.value || Object.keys(myChart.value).length === 0) {
  46. myChart.value = echarts.init(canvas.value);
  47. }
  48. // 基于准备好的dom,初始化echarts实例
  49. myChart.value.clear();
  50. myChart.value.setOption(props.option);
  51. // 监听元素变化
  52. const erd = ElementResizeDetectorMaker();
  53. erd.listenTo(canvas.value, function () {
  54. nextTick(function () {
  55. // 使echarts尺寸重置
  56. setTimeout(function () {
  57. myChart.value.resize();
  58. }, 500);
  59. });
  60. });
  61. if (props.rotation) {
  62. autoToolTip(myChart.value, props.option, { loopSeries: true });
  63. }
  64. emits('ready', myChart.value);
  65. // 监听点击事件
  66. if (props.chartClick) {
  67. myChart.value.off('click', handleClick);
  68. myChart.value.on('click', handleClick);
  69. }
  70. if (props.legendChange) {
  71. myChart.value.on('legendselectchanged', function (params) {
  72. props.legendChange(params, myChart.value);
  73. });
  74. }
  75. loaded.value = true;
  76. };
  77. const handleClick = (params: any) => {
  78. props.chartClick(params);
  79. };
  80. onMounted(() => {
  81. if (!(JSON.stringify(props.option) === '{}')) {
  82. load();
  83. }
  84. });
  85. onUnmounted(() => {
  86. myChart.value = null;
  87. });
  88. </script>
  89. <style lang="scss" scoped>
  90. .canvas {
  91. width: 100%;
  92. height: 100%;
  93. // flex: 1;
  94. }
  95. </style>