echarts.tsx 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. "use client"
  2. import React, {useEffect, useRef} from "react"
  3. import {
  4. type ECharts,
  5. type EChartsCoreOption,
  6. getInstanceByDom,
  7. init as echartsInit,
  8. type SetOptionOpts,
  9. use as echartsUse
  10. } from "echarts/core"
  11. import {BarChart, GaugeChart, HeatmapChart, LineChart, PieChart, RadarChart, ScatterChart} from "echarts/charts"
  12. import {
  13. DatasetComponent,
  14. GraphicComponent,
  15. GridComponent,
  16. LegendComponent,
  17. TitleComponent,
  18. ToolboxComponent,
  19. TooltipComponent,
  20. VisualMapComponent,
  21. } from "echarts/components"
  22. import {CanvasRenderer} from "echarts/renderers"
  23. echartsUse([
  24. BarChart,
  25. HeatmapChart,
  26. LineChart,
  27. PieChart,
  28. GaugeChart,
  29. RadarChart,
  30. ScatterChart,
  31. GridComponent,
  32. TooltipComponent,
  33. LegendComponent,
  34. TitleComponent,
  35. ToolboxComponent,
  36. VisualMapComponent,
  37. DatasetComponent,
  38. GraphicComponent,
  39. CanvasRenderer,
  40. ])
  41. export type EChartProps = {
  42. option: EChartsCoreOption
  43. className?: string
  44. style?: React.CSSProperties
  45. theme?: "light" | "dark"
  46. opts?: SetOptionOpts
  47. }
  48. export default function EChart({ option, className, style, theme = "light", opts }: EChartProps) {
  49. const ref = useRef<HTMLDivElement | null>(null)
  50. const chartRef = useRef<ECharts | null>(null)
  51. useEffect(() => {
  52. if (!ref.current) return
  53. const el = ref.current
  54. let chart = getInstanceByDom(el)
  55. if (!chart) {
  56. chart = echartsInit(el, theme, { renderer: "canvas", locale: "ZH" })
  57. }
  58. chartRef.current = chart
  59. // Apply option
  60. chart.setOption(option, opts)
  61. const resize = () => chart && chart.resize()
  62. window.addEventListener("resize", resize)
  63. // Resize observer for container changes
  64. const ro = new ResizeObserver(() => resize())
  65. ro.observe(el)
  66. return () => {
  67. window.removeEventListener("resize", resize)
  68. ro.disconnect()
  69. // dispose only if element is being removed to avoid issues in fast refresh
  70. if (chart && !el.isConnected) {
  71. chart.dispose()
  72. chartRef.current = null
  73. }
  74. }
  75. }, [option, theme, opts])
  76. return <div ref={ref} className={className} style={{ width: "100%", height: 320, ...style }} />
  77. }