|
@@ -0,0 +1,174 @@
|
|
|
|
|
+import { echarts } from "@@/plugins/echarts"
|
|
|
|
|
+import { useDebounceFn, useResizeObserver } from "@vueuse/core"
|
|
|
|
|
+import type { EChartsCoreOption, EChartsInitOpts, SetOptionOpts } from "echarts"
|
|
|
|
|
+
|
|
|
|
|
+type NullType<T> = T | null
|
|
|
|
|
+
|
|
|
|
|
+interface ConfigProps {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * init函数基本配置
|
|
|
|
|
+ * @see https://echarts.apache.org/zh/api.html#echarts.init
|
|
|
|
|
+ */
|
|
|
|
|
+ echartsInitOpts?: EChartsInitOpts
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 是否显示loading
|
|
|
|
|
+ * @default false
|
|
|
|
|
+ */
|
|
|
|
|
+ loading?: boolean
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Loading配置项
|
|
|
|
|
+ * @see https://echarts.apache.org/zh/api.html#echartsInstance.showLoading
|
|
|
|
|
+ */
|
|
|
|
|
+ loadingOption?: object
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 是否开启过渡动画
|
|
|
|
|
+ * @default true
|
|
|
|
|
+ */
|
|
|
|
|
+ animation?: boolean
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 过渡动画持续时间(ms)
|
|
|
|
|
+ * @default 300
|
|
|
|
|
+ */
|
|
|
|
|
+ animationDuration?: number
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 是否自动调整大小
|
|
|
|
|
+ * @default true
|
|
|
|
|
+ */
|
|
|
|
|
+ autoResize?: boolean
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 防抖时间(ms)
|
|
|
|
|
+ * @default 300
|
|
|
|
|
+ */
|
|
|
|
|
+ resizeDebounceWait?: number
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 最大防抖时间(ms)
|
|
|
|
|
+ * @default 500
|
|
|
|
|
+ */
|
|
|
|
|
+ maxResizeDebounceWait?: number
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const DEFAULT_CONFIG: ConfigProps = {
|
|
|
|
|
+ loading: true,
|
|
|
|
|
+ loadingOption: {
|
|
|
|
|
+ text: "加载中...",
|
|
|
|
|
+ color: "#c23531",
|
|
|
|
|
+ textColor: "#000",
|
|
|
|
|
+ maskColor: "rgba(255, 255, 255, 0.8)",
|
|
|
|
|
+ zlevel: 0,
|
|
|
|
|
+ // 字体大小。从 `v4.8.0` 开始支持。
|
|
|
|
|
+ fontSize: 12,
|
|
|
|
|
+ // 是否显示旋转动画(spinner)。从 `v4.8.0` 开始支持。
|
|
|
|
|
+ showSpinner: true,
|
|
|
|
|
+ // 旋转动画(spinner)的半径。从 `v4.8.0` 开始支持。
|
|
|
|
|
+ spinnerRadius: 10,
|
|
|
|
|
+ // 旋转动画(spinner)的线宽。从 `v4.8.0` 开始支持。
|
|
|
|
|
+ lineWidth: 3,
|
|
|
|
|
+ // 字体粗细。从 `v5.0.1` 开始支持。
|
|
|
|
|
+ fontWeight: "normal",
|
|
|
|
|
+ // 字体风格。从 `v5.0.1` 开始支持。
|
|
|
|
|
+ fontStyle: "normal",
|
|
|
|
|
+ // 字体系列。从 `v5.0.1` 开始支持。
|
|
|
|
|
+ fontFamily: "sans-serif"
|
|
|
|
|
+ },
|
|
|
|
|
+ animation: true,
|
|
|
|
|
+ animationDuration: 300,
|
|
|
|
|
+ autoResize: true,
|
|
|
|
|
+ resizeDebounceWait: 300,
|
|
|
|
|
+ maxResizeDebounceWait: 500
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export const useEcharts = (
|
|
|
|
|
+ dom: Ref<HTMLDivElement | HTMLCanvasElement | null>,
|
|
|
|
|
+ config?: ConfigProps
|
|
|
|
|
+) => {
|
|
|
|
|
+ const {
|
|
|
|
|
+ echartsInitOpts,
|
|
|
|
|
+ loading,
|
|
|
|
|
+ animation,
|
|
|
|
|
+ animationDuration,
|
|
|
|
|
+ autoResize,
|
|
|
|
|
+ resizeDebounceWait,
|
|
|
|
|
+ maxResizeDebounceWait
|
|
|
|
|
+ } = Object.assign({}, DEFAULT_CONFIG, config)
|
|
|
|
|
+ const loadingOption = Object.assign({}, DEFAULT_CONFIG.loadingOption, config?.loadingOption)
|
|
|
|
|
+ /** 图表实例 */
|
|
|
|
|
+ let chartInstance: NullType<echarts.ECharts> = null
|
|
|
|
|
+
|
|
|
|
|
+ /** Loading 状态控制 */
|
|
|
|
|
+ const toggleLoading = (show: boolean) => {
|
|
|
|
|
+ if (!chartInstance) return
|
|
|
|
|
+ if (!loading) return
|
|
|
|
|
+ show ? chartInstance.showLoading("default", loadingOption) : chartInstance.hideLoading()
|
|
|
|
|
+ }
|
|
|
|
|
+ /** 图表初始化 */
|
|
|
|
|
+ const initChart = () => {
|
|
|
|
|
+ if (!dom.value || echarts.getInstanceByDom(dom.value)) return
|
|
|
|
|
+ chartInstance = echarts.init(dom.value, null, echartsInitOpts)
|
|
|
|
|
+ toggleLoading(true)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 获取图表实例 */
|
|
|
|
|
+ const getChartInstance = () => chartInstance
|
|
|
|
|
+
|
|
|
|
|
+ // SetOptionOpts:
|
|
|
|
|
+ // (option: Object, opts?: {
|
|
|
|
|
+ // notMerge?: boolean;// 是否不跟之前设置的 `option` 进行合并
|
|
|
|
|
+ // replaceMerge?: string | string[];// 用户可以在这里指定一个或多个组件
|
|
|
|
|
+ // lazyUpdate?: boolean;// 在设置完 `option` 后是否不立即更新图表
|
|
|
|
|
+ // })
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 图表渲染
|
|
|
|
|
+ * @param options 图表数据集
|
|
|
|
|
+ * @param opts 图表配置项
|
|
|
|
|
+ */
|
|
|
|
|
+ const renderChart = (options: EChartsCoreOption, opts: SetOptionOpts = { notMerge: true }) => {
|
|
|
|
|
+ if (!chartInstance) {
|
|
|
|
|
+ initChart()
|
|
|
|
|
+ }
|
|
|
|
|
+ const finalOptions = { ...options, backgroundColor: "transparent" }
|
|
|
|
|
+ // console.log("renderChart", finalOptions)
|
|
|
|
|
+ chartInstance.setOption(finalOptions, opts)
|
|
|
|
|
+ toggleLoading(false)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 图表销毁 */
|
|
|
|
|
+ const destroyChart = () => {
|
|
|
|
|
+ if (!chartInstance) return
|
|
|
|
|
+ chartInstance.dispose()
|
|
|
|
|
+ chartInstance = null
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 调整图表尺寸 */
|
|
|
|
|
+ const resize = () => {
|
|
|
|
|
+ if (!chartInstance) return
|
|
|
|
|
+ chartInstance.resize({
|
|
|
|
|
+ animation: {
|
|
|
|
|
+ duration: animation ? animationDuration : 0
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ /** 防抖处理的resize */
|
|
|
|
|
+ const resizeDebounce = useDebounceFn(resize, resizeDebounceWait, {
|
|
|
|
|
+ maxWait: maxResizeDebounceWait
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ onMounted(() => {
|
|
|
|
|
+ initChart()
|
|
|
|
|
+ if (autoResize) {
|
|
|
|
|
+ useResizeObserver(dom, resizeDebounce)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 组件实例被卸载之后
|
|
|
|
|
+ onUnmounted(() => {
|
|
|
|
|
+ destroyChart()
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ echarts,
|
|
|
|
|
+ chartInstance,
|
|
|
|
|
+ getChartInstance,
|
|
|
|
|
+ renderChart,
|
|
|
|
|
+ toggleLoading
|
|
|
|
|
+ }
|
|
|
|
|
+}
|